package com.yanqu.road.server.manager.chefduel;

import com.google.protobuf.AbstractMessage;
import com.yanqu.road.dao.impl.cross.chefduel.CrossChefDuelDaoImpl;
import com.yanqu.road.dao.impl.player.CrossCommonActivityDataDaoImpl;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.chefduel.CrossChefDuel2Rank;
import com.yanqu.road.entity.activity.chefduel.CrossChefDuel2RankListModel;
import com.yanqu.road.entity.activity.chefduel.process2.*;
import com.yanqu.road.entity.activity.chefduel.rank.CampRank;
import com.yanqu.road.entity.activity.chefduel.rank.CampRankListModel;
import com.yanqu.road.entity.log.chefduel.ChefDuel2AutoJoinLog;
import com.yanqu.road.entity.autodata.chefduel2.ChefDuel2AutoJoinRecord;
import com.yanqu.road.entity.autodata.chefduel2.CrossChefDuel2AutoJoinSpoon;
import com.yanqu.road.entity.log.chefduel.LogChefDuel2East;
import com.yanqu.road.entity.log.chefduel.LogChefDuel2End;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.rank.cross.CrossUserRank;
import com.yanqu.road.logic.cross.CrossActivityRankListModel;
import com.yanqu.road.logic.pb.CrossActivityPb;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.thread.ThreadTaskManger;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.chefduel.ChefDuelProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.relation.CrossRelationRankMgr;
import com.yanqu.road.server.manager.log.CrossAutoLogMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.pb.chefduel.CrossChefDuelPb;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.util.ConcurrentHashSet;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class CrossChefDuel2 {

    private Logger logger = LogManager.getLogger(CrossChefDuel2.class.getName());

    private ActivityInfo activityInfo;

    private Map<Long, ChefDuelUpUser> chefDuelMap = new ConcurrentHashMap<>();

    //阵营人气
    Map<Integer, Integer> campCountMap = new HashMap<>();
    //阵营积分
    CampRankListModel campRankListModel = new CampRankListModel();
    //阵营玩家榜单
    Map<Integer, CrossChefDuel2RankListModel> campUserRankMap = new ConcurrentHashMap<>();

    private List<ChefDuelUpUser> needSyncUserList = new ArrayList<>();
    private List<ChefDuelUpUser> needInsertUserList = new ArrayList<>();
    private List<ChefDuelUpUser> needUpdateUserList = new ArrayList<>();

    //index
    private List<HorseRaceLamp> needHorseRaceLampList = new ArrayList<>();//同步跑马灯

    //用户id场次no
    private Map<Long,Map<Integer, ChefDuel2DishTable>> chefDuelTableMap = new ConcurrentHashMap<>();

    //正在开还没结束的桌子
    private Map<Long,Map<Integer, ChefDuel2DishTable>> openChefDuelTableMap = new ConcurrentHashMap<>();

    private List<ChefDuel2DishTable> needInsertTableList = new ArrayList<>();
    private List<ChefDuel2DishTable> needUpdateTableList = new ArrayList<>();

    //用户的互宴信息
    private List<ChefDuel2UserJoinData> joinList = new ArrayList<>();

    //大的userId
    private Map<Long,ChefDuel2UserJoinData> joinMap = new ConcurrentHashMap<>();

    private List<ChefDuel2UserJoinData> joinInsertList = new ArrayList<>();
    private List<ChefDuel2UserJoinData> joinUpdateList = new ArrayList<>();

    //待同步的区服
    private Set<Long> syncServerIdList;

    // 自动回访线程池
    private ThreadTaskManger autoJoinThreadPool;

    private Map<Long, CrossChefDuel2AutoJoinSpoon> autoJoinSpoonMap = new HashMap<>(); // 自动回访汤勺
    private Map<Long, Map<Long, ChefDuel2AutoJoinRecord>> autoJoinRecordMap = new HashMap<>(); // 自动回访记录

    //回宴设置变更
    private Set<Long> spoonSettingChangeSet = new HashSet<>();

    public int getActivityId(){
        return activityInfo.getActivityId();
    }

    public ActivityInfo getActivityInfo(){
        return activityInfo;
    }

    public boolean activityInWindUpTime() {
        if(null == activityInfo){
            return false;
        }
        long nowTime = System.currentTimeMillis() / 1000;
        return nowTime >= activityInfo.getEndTime() + 5 * 60 && nowTime < activityInfo.getEndShowTime();
    }

    //活动结束结算下发晋级人员
    public void activityEndWindUp(){
        if(activityInWindUpTime()){
            //活动结束了移除数据
            chefDuelTableMap = new ConcurrentHashMap<>();
            joinMap = new ConcurrentHashMap<>();

            List<ChefDuel2UserJoinData> tempRemoveList = new ArrayList<>();
            for(ChefDuel2UserJoinData chefDuel2UserJoinData : joinList){
                if(chefDuel2UserJoinData != null && chefDuel2UserJoinData.getActivityId() == getActivityId()){
                    tempRemoveList.add(chefDuel2UserJoinData);
                }
            }
            for(ChefDuel2UserJoinData a : tempRemoveList){
                joinList.remove(a);
            }
            //rank userId
//            Map<Integer,Long> goodBoyMap = new ConcurrentHashMap<>();
            //同步给本服
            Map<Long, List<ChefDuelProto.CrossChefDuelWindUpCookerTempMsg>> goodBoyServerSyncMap = new ConcurrentHashMap<>();

            int minRank = CrossChefDuelActivityMgr.getCook2ToCook3Rank(getActivityId());

            CrossActivityRankListModel rankListModel = CrossRelationRankMgr.getCrossActivityRankListModel(getActivityId());
            if(rankListModel == null){
                //启动的时候可能还没全部启动完定时器已经开始跑了，排行榜还没加载完。。。。
                return;
            }
            LinkedList<CrossUserRank> rankList = rankListModel.getRankList();
            int rank = 1;
            for(CrossUserRank userRank : rankList){
                if(rank <= minRank){
//                    logger.error("阶段2晋级阶段3下发数据，配置文件晋级的排名要求"+rank+",晋级的玩家id:"+userRank.getUserId()+",玩家排名"+rank+",userRank排名:"+userRank.getRank());
//                    goodBoyMap.put(userRank.getRank(),userRank.getUserId());
                    if(!goodBoyServerSyncMap.containsKey(userRank.getUserBaseInfo().getServerId())){
                        goodBoyServerSyncMap.put(userRank.getUserBaseInfo().getServerId(),new ArrayList<>());
                    }
                    ChefDuelProto.CrossChefDuelWindUpCookerTempMsg.Builder builder = ChefDuelProto.CrossChefDuelWindUpCookerTempMsg.newBuilder();
                    builder.setRank(rank);
                    builder.setScore(userRank.getValue().longValue());
                    builder.setUserId(userRank.getUserId());
                    goodBoyServerSyncMap.get(userRank.getUserBaseInfo().getServerId()).add(builder.build());
                }
                rank++;
            }
            windUpChefDuel1UserSyncServer(goodBoyServerSyncMap);
        }
    }

    public void windUpChefDuel1UserSyncServer(Map<Long, List<ChefDuelProto.CrossChefDuelWindUpCookerTempMsg>> goodBoyServerSyncMap){
        for(Long serverId : goodBoyServerSyncMap.keySet()){
            ChefDuelProto.CrossChefDuelWindUpMsg.Builder respMsg =
                    CrossChefDuelPb.parseCrossChefDuelWindUpMsg(activityInfo.getActivityId(), goodBoyServerSyncMap.get(serverId));
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_TO_CHEF_DUEL3, respMsg);
            MessageHelper.sendPacket(serverId, 0, pbMsg);
        }
    }

    public void addChefDuel2Horse(long serverId, long userId, int dishId, long time) {
        synchronized (needHorseRaceLampList){
            HorseRaceLamp horseRaceLamp = new HorseRaceLamp();
            horseRaceLamp.setServerId(serverId);
            horseRaceLamp.setUserId(userId);
            horseRaceLamp.setDishId(dishId);
            horseRaceLamp.setTime(time);
            needHorseRaceLampList.add(horseRaceLamp);
        }
        ChefDuelProto.ChefDuel2horseRaceLampSyncMsg.Builder userHorseMsg = ChefDuelProto.ChefDuel2horseRaceLampSyncMsg.newBuilder();
        ChefDuelProto.ChefDuel2horseRaceLampTempMsg.Builder tempMsg = ChefDuelProto.ChefDuel2horseRaceLampTempMsg.newBuilder();
        tempMsg.setUserId(userId);
        tempMsg.setDishId(dishId);
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if(userBaseInfo == null){
            return;
        }
        tempMsg.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
        userHorseMsg.addNoticeList(tempMsg);
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CROSS_CHEF_DUEL2_HORSE_NOTICE_SYNC, userHorseMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    public void syncHorseNotice(){
        List<HorseRaceLamp> snycList = new ArrayList<>();
        synchronized (needHorseRaceLampList) {
            snycList = new ArrayList<>(needHorseRaceLampList);
            needHorseRaceLampList.clear();
        }
        if(snycList.size() > 0){
            ChefDuelProto.CrossChefDuel2HorseSyncServerMsg.Builder respMsg =
                    CrossChefDuelPb.parseChefDuel2HorseSyncServerMsg(snycList,getActivityId());
            if(respMsg != null){
                for(long serverId : activityInfo.getServerIdList2()){
                    YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_HORSE_NOTICE_SYNC, respMsg);
                    MessageHelper.sendPacket(serverId, 0, pbMsg);
                }
            }
        }
    }

    private void removeOpenTable(ChefDuel2DishTable chefDuel2DishTable){
        if(openChefDuelTableMap.containsKey(chefDuel2DishTable.getUserId())){
            openChefDuelTableMap.get(chefDuel2DishTable.getUserId()).remove(chefDuel2DishTable.getNo());
        }
    }

    private void addOpenTable(ChefDuel2DishTable chefDuel2DishTable){
        if(!openChefDuelTableMap.containsKey(chefDuel2DishTable.getUserId())){
            openChefDuelTableMap.put(chefDuel2DishTable.getUserId(),new ConcurrentHashMap<>());
        }
        openChefDuelTableMap.get(chefDuel2DishTable.getUserId()).put(chefDuel2DishTable.getNo(),chefDuel2DishTable);
    }

    private Map<ChefDuel2DishTable, YanQuMessage> endTableMsgMap = new ConcurrentHashMap<>();

    private ChefDuel2TableReward endTable(ChefDuel2DishTable chefDuel2DishTable){
        ChefDuel2TableReward res = null;
        if(chefDuel2DishTable.getOverTime() == 0){
            res = new ChefDuel2TableReward();
            chefDuel2DishTable.setOverTime(System.currentTimeMillis());
            removeOpenTable(chefDuel2DishTable);
            res.setActivityId(getActivityId());
            res.setUserId(chefDuel2DishTable.getUserId());
            //结束了加上没坐完的自动填充机器人那部分积分
            ChefDuel2Spoon chefDuel2Spoon = CrossChefDuelActivityMgr.getChefDuel2MinSpoon(getActivityId());
            ChefDuel2DishConfig chefDuel2DishConfig = CrossChefDuelActivityMgr.getDishCondfig(getActivityId(),chefDuel2DishTable.getDishId());
            int needAddNum = chefDuel2DishConfig.getSeat() - chefDuel2DishTable.getChefDuel2JoinerMap().size();


            long addIntegral = 0;
            if(needAddNum > 0){
                Map<Long, ChefDuel2Joiner> joinerMap = chefDuel2DishTable.getChefDuel2JoinerMap();
                for(int i = 0;i < needAddNum;i++){
                    int robotId = CrossChefDuelActivityMgr.getRandomChefDuel2Robot(getActivityId());
                    ChefDuel2Joiner chefDuel2Joiner = new ChefDuel2Joiner();
                    chefDuel2Joiner.setServerId(0);
                    chefDuel2Joiner.setUserId(joinerMap.size() + 1);
                    chefDuel2Joiner.setGifttId(chefDuel2Spoon.getItemId());
                    chefDuel2Joiner.setPos(joinerMap.size() + 1);
                    chefDuel2Joiner.setRobotId(robotId);
                    joinerMap.put(chefDuel2Joiner.getUserId(),chefDuel2Joiner);
                }
                chefDuel2DishTable.setChefDuel2JoinerMap(joinerMap);
                addIntegral  = chefDuel2Spoon.getUserIntegral() * needAddNum * CrossChefDuelActivityMgr.getChefDuel2RobotAdd(getActivityId()) / 1000;
                chefDuel2DishTable.setIntegral(chefDuel2DishTable.getIntegral() + addIntegral);
                res.setIntegral(addIntegral);
                res.setSeatNum(needAddNum);
            }
            //同步结束了
            addToEndTableMsg(chefDuel2DishTable, addIntegral);
//            MessageHelper.sendChannelPacket(chefDuel2DishTable.getServerId(), chefDuel2DishTable.getUserId(), pbOpenerMsg);
            synchronized (needUpdateTableList){
                if(!needUpdateTableList.contains(chefDuel2DishTable)){
                    needUpdateTableList.add(chefDuel2DishTable);
                }
            }
            synchronized (needSyncUserList){
                if (!needSyncUserList.contains(chefDuelMap.get(chefDuel2DishTable.getUserId()))) {
                    needSyncUserList.add(chefDuelMap.get(chefDuel2DishTable.getUserId()));
                }
            }
            //日志
            ChefDuelUpUser chefDuelUpUser = chefDuelMap.get(chefDuel2DishTable.getUserId());
            CrossAutoLogMgr.add(new LogChefDuel2End(
                    activityInfo.getActivityId(),
                    chefDuel2DishTable.getUserId(),
                    chefDuelUpUser.getCampId(),
                    chefDuel2DishTable.getNo(),
                    chefDuel2DishTable.getDishId() + "=1",
                    StringUtils.listToString(new ArrayList(chefDuel2DishTable.getChefDuel2JoinerMap().keySet()), ","),
                    addIntegral,
                    chefDuel2DishTable.getOpenTime()
            ));
        }
        return res;
    }

    private void addToEndTableMsg(ChefDuel2DishTable chefDuel2DishTable, long addIntegral) {
        ChefDuelProto.CrossChefDuel2RobotJoinBanquetMsg.Builder msg = ChefDuelProto.CrossChefDuel2RobotJoinBanquetMsg.newBuilder();
        msg.setRet(0);
        msg.setIntegral(addIntegral);
        msg.setActivityId(getActivityId());
        msg.setHomeUserId(chefDuel2DishTable.getUserId());
        msg.setDishId(chefDuel2DishTable.getDishId());
        msg.setTableId(chefDuel2DishTable.getNo());
        msg.setUserDishId(chefDuel2DishTable.getUserDishId());
        msg.setAllIntegral(chefDuel2DishTable.getIntegral());
        YanQuMessage pbOpenerMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_ROBOT_JOIN, msg);
        synchronized (endTableMsgMap) {
            endTableMsgMap.put(chefDuel2DishTable,pbOpenerMsg);
        }
    }

    public void tableCheck(){
        for(long userId : chefDuelTableMap.keySet()){
            List<ChefDuel2DishTable> needSyncTableList = new ArrayList<>();
            long addIntegral = 0;
            Map<Integer,ChefDuel2DishTable> userMap = chefDuelTableMap.get(userId);
            for (Map.Entry<Integer, ChefDuel2DishTable> entry : userMap.entrySet()) {
                ChefDuel2DishTable chefDuel2DishTable = entry.getValue();
                if(chefDuel2DishTable.getOverTime() != 0)continue;
                ChefDuel2TableReward eatTableRes = null;
                ChefDuel2DishConfig chefDuel2DishConfig = CrossChefDuelActivityMgr.getDishCondfig(getActivityId(),chefDuel2DishTable.getDishId());
                if(chefDuel2DishConfig == null){
                    logger.error("厨神对决2找不到配置的菜品id"+chefDuel2DishTable.getDishId());
                    continue;
                }
                synchronized (chefDuel2DishTable) {
                    //时间到了结束//座位坐满了结束//每天到了晚上22点也结束
                    if(System.currentTimeMillis() - chefDuel2DishTable.getOpenTime() > CrossChefDuelActivityMgr.getServeDishTableTime(getActivityId()) * 60 * 1000 ||
                        chefDuel2DishTable.getChefDuel2JoinerMap().size() >= chefDuel2DishConfig.getSeat() ||
                        !CrossChefDuelActivityMgr.isActivityMatchTime(activityInfo)){
                        eatTableRes = endTable(chefDuel2DishTable);
                    }
                }
                if(eatTableRes != null){
                    needSyncTableList.add(chefDuel2DishTable);
                    addIntegral = addIntegral + eatTableRes.getIntegral();
                }
            }
            if(needSyncTableList.size() > 0){
                //把机器人的积分也同步下去，不然客户端刷新不准，会等通知积分通知本服，本服触发condition，再到跨服排行，才有他的积分
                syncTableServers(userId,needSyncTableList,addIntegral);
                synchronized (endTableMsgMap) {
                    for (ChefDuel2DishTable chefDuel2DishTable :endTableMsgMap.keySet()){
                        MessageHelper.sendPacket(chefDuel2DishTable.getServerId(), chefDuel2DishTable.getUserId(), endTableMsgMap.get(chefDuel2DishTable));
                    }
                    endTableMsgMap.clear();
                }
                synchronized (needSyncUserList){
                    if(!needSyncUserList.contains(chefDuelMap.get(userId))){
                        needSyncUserList.add(chefDuelMap.get(userId));
                    }
                }
            }else {
                synchronized (endTableMsgMap) {
                    for (ChefDuel2DishTable chefDuel2DishTable :endTableMsgMap.keySet()){
                        MessageHelper.sendPacket(chefDuel2DishTable.getServerId(), chefDuel2DishTable.getUserId(), endTableMsgMap.get(chefDuel2DishTable));
                    }
                    endTableMsgMap.clear();
                }
            }
        }
//        syncCookerServer();
    }

    //addIntegral把参加的人的积分加上去，要同步这个玩家的积分变化，不然要等到本服加上后同步到跨服排行榜,机器人的也没加，不管了
    public void syncTableServer(ChefDuel2DishTable chefDuel2DishTable,long addIntegral){
        int dishNum = 0;
        if(chefDuelTableMap.containsKey(chefDuel2DishTable.getUserId())){
            dishNum = chefDuelTableMap.get(chefDuel2DishTable.getUserId()).size();
        }
        try {
            Map<Integer, ChefDuel2DishTable> tableMap = new ConcurrentHashMap<>();
            tableMap.put(chefDuel2DishTable.getNo(), chefDuel2DishTable);
            ChefDuelProto.CrossChefDuel2TableSyncMsg.Builder respMsg =
                    CrossChefDuelPb.parseCrossChefDuel2TableSyncMsg(tableMap, getActivityId(), chefDuel2DishTable.getServerId(), chefDuel2DishTable.getUserId(), dishNum, addIntegral);
            for(long serverId : activityInfo.getServerIdList2()){
                YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_TABLE_SYNC, respMsg);
                MessageHelper.sendPacket(serverId, 0, pbMsg);
            }
        }catch (Exception e){
            logger.error("", e);
        }
    }

    public void syncTableServers(long userId, List<ChefDuel2DishTable> chefDuel2DishTableList,long addIntegral){
        if(chefDuel2DishTableList.size() == 0){
            return;
        }
        int dishNum = 0;
        if(chefDuelTableMap.containsKey(userId)){
            dishNum = chefDuelTableMap.get(userId).size();
        }
        Map<Integer,ChefDuel2DishTable> tableMap = new ConcurrentHashMap<>();
        for(ChefDuel2DishTable chefDuel2DishTable : chefDuel2DishTableList){
            tableMap.put(chefDuel2DishTable.getNo(),chefDuel2DishTable);
        }
        try {
            ChefDuelProto.CrossChefDuel2TableSyncMsg.Builder respMsg =
                    CrossChefDuelPb.parseCrossChefDuel2TableSyncMsg(tableMap, getActivityId(), chefDuelMap.get(userId).getServerId(), userId, dishNum, addIntegral);
            for(long serverId : activityInfo.getServerIdList2()){
                YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_TABLE_SYNC, respMsg);
                MessageHelper.sendPacket(serverId, 0, pbMsg);
            }
        }catch (Exception e){
            logger.error("", e);
        }
    }

    //获取这个人不能试吃的人
    private List<Long> getCookerNoEatUserIdList(long cookerId){
        Map<Long,Integer> eatCountMap = new ConcurrentHashMap<>();
        List<Long> noEatUserIdList = new ArrayList<>();
        if(!openChefDuelTableMap.containsKey(cookerId) || openChefDuelTableMap.get(cookerId).size() == 0){
            return null;
        }
        Map<Integer, ChefDuel2DishTable> openTableMap = openChefDuelTableMap.get(cookerId);
        for(ChefDuel2DishTable table : openTableMap.values()){
            Map<Long, ChefDuel2Joiner> joinerMap = table.getChefDuel2JoinerMap();
            for(ChefDuel2Joiner joiner : joinerMap.values()){
                if(eatCountMap.containsKey(joiner.getUserId())){
                    eatCountMap.put(joiner.getUserId(),eatCountMap.get(joiner.getUserId()) + 1);
                }else{
                    eatCountMap.put(joiner.getUserId(),1);
                }
            }
        }
        for(Long userId : eatCountMap.keySet()){
            if(eatCountMap.get(userId) == openTableMap.size()){
                noEatUserIdList.add(userId);
            }
        }
        return noEatUserIdList;
    }

    //给桌子排下名
    private void cookerRanking(){
        for(ChefDuelUpUser chefDuelUpUser : chefDuelMap.values()){
            if(!chefDuelTableMap.containsKey(chefDuelUpUser.getUserId())){
                chefDuelUpUser.setIntegral(0);
                chefDuelUpUser.setRank(0);
            }else{
                Map<Integer, ChefDuel2DishTable> chefDuel2DishTableMap = chefDuelTableMap.get(chefDuelUpUser.getUserId());
                long integral = 0;
                for(ChefDuel2DishTable chefDuel2DishTable : chefDuel2DishTableMap.values()){
                    integral += chefDuel2DishTable.getIntegral();
                }
                chefDuelUpUser.setIntegral(integral);
            }
        }
        List<ChefDuelUpUser> cookerList = new ArrayList<>(chefDuelMap.values());
        cookerList.sort(new CookerSort());
        int rank = 1;
        for(ChefDuelUpUser chefDuelUpUser : cookerList){
            chefDuelUpUser.setRank(rank);
            rank++;
        }
    }

    public void setActivityInfo(ActivityInfo activityInfo){
//        repair();
        this.activityInfo = activityInfo;
    }

    public void checkDishStatus(long serverId, List<ChefDuelProto.NeedCheckChefDuel2DishMsg> dishList) {
        for (ChefDuelProto.NeedCheckChefDuel2DishMsg dishMsg : dishList) {
            long userId = dishMsg.getUserId();
            int dishId = dishMsg.getDishId();
            Map<Integer, ChefDuel2DishTable> tableMap = chefDuelTableMap.get(userId);
            if (tableMap == null) {
                continue;
            }
            ChefDuel2DishTable dishTable = tableMap.get(dishId);
            if (dishTable == null) {
                continue;
            }
            if (dishTable.getOverTime() == 0 || System.currentTimeMillis() - dishTable.getOverTime() < 30*1000L) {
                continue;
            }
            int needAddNum = 0;
            for (ChefDuel2Joiner joiner : new ArrayList<>(dishTable.getChefDuel2JoinerMap().values())) {
                if (joiner.getRobotId() != 0) {
                    needAddNum++;
                }
            }
            long addIntegral = 0;
            if (needAddNum > 0) {
                ChefDuel2Spoon chefDuel2Spoon = CrossChefDuelActivityMgr.getChefDuel2MinSpoon(getActivityId());
                addIntegral  = chefDuel2Spoon.getUserIntegral() * needAddNum * CrossChefDuelActivityMgr.getChefDuel2RobotAdd(getActivityId()) / 1000;
            }
            addToEndTableMsg(dishTable,addIntegral);
        }
    }

    public void syncActivityBack(long serverId) {
        syncServerIdList.remove(serverId);
    }

    public void setSyncServerIdList(Set<Long> syncServerIdList) {
        this.syncServerIdList = syncServerIdList;
    }

    public int selectCampId(long serverId, long playerId, int campId) {
        ChefDuelUpUser cookData = chefDuelMap.get(playerId);
        if(cookData == null){
            return GameErrorCode.E_CHEF_DUEL2_USER_NOT_ABLE;
        }
        if(cookData.getCampId() > 0){
            return GameErrorCode.E_CHEF_DUEL2_CAMP_CHANGE_ERROR;
        }
        cookData.setCampId(campId);
        synchronized (needUpdateUserList){
            if(!needUpdateUserList.contains(cookData)){
                needUpdateUserList.add(cookData);
            }
        }
        MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_SELECT_CAMP,
                ChefDuelProto.ChefDuel2CampSelectRespMsg.newBuilder().setRet(0).setCampId(campId).setActivityId(cookData.getActivityId())));
        return 0;
    }

    public int campPopNum(long serverId, long playerId) {
        ChefDuelProto.ChefDuel2CampListRespMsg.Builder clientMsg = ChefDuelProto.ChefDuel2CampListRespMsg.newBuilder();
        clientMsg.setRet(0);
        int camp1 = campCountMap.getOrDefault(1, 0);
        clientMsg.addCampNum(camp1);
        int camp2 = campCountMap.getOrDefault(2, 0);
        clientMsg.addCampNum(camp2);
        MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_CAMP_POPULARITY, clientMsg));
        return 0;
    }

    public void timerTask4Stat() {
        int currentSecond = DateHelper.getCurrentSecond();
        //活动结束4分钟后不再统计
        if(currentSecond >= this.activityInfo.getEndTime() + 4 * DateHelper.MINUTE_SECONDS){
            return;
        }
        Map<Integer, Integer> campCountMap = new HashMap<>();
        Map<Integer, Long> campScoreMap = new HashMap<>();
        Map<Integer, Long> campScoreLastTimeMap = new HashMap<>();
        Map<Integer, LinkedList<CrossChefDuel2Rank>> rankList = new HashMap<>();
        for (Map.Entry<Long, ChefDuelUpUser> entry : chefDuelMap.entrySet()) {
            int campId = entry.getValue().getCampId();
            if(campId <= 0){
                continue;
            }
            //阵营人气
            int old = campCountMap.getOrDefault(campId, 0);
            campCountMap.put(campId, old + 1);
            long score = campScoreMap.getOrDefault(campId, 0L);
            campScoreMap.put(campId, score + entry.getValue().getRankIntegral());

            long time = campScoreLastTimeMap.getOrDefault(campId, 0L);
            if(time < entry.getValue().getRankTime() && entry.getValue().getRankTime() > 0 && entry.getValue().getRankIntegral() > 0){
                campScoreLastTimeMap.put(campId, entry.getValue().getRankTime());
            }

            //阵营玩家榜单
            if(!rankList.containsKey(campId)){
                rankList.put(campId, new LinkedList<>());
            }
            rankList.get(campId).add(new CrossChefDuel2Rank(entry.getValue().getUserId(), entry.getValue().getRankIntegral(), entry.getValue().getRankTime()));
        }
        this.campCountMap = campCountMap;

        for (Map.Entry<Integer, Long> entry : campScoreMap.entrySet()) {
            if(entry.getValue() > 0) {
                long time = campScoreLastTimeMap.getOrDefault(entry.getKey(), System.currentTimeMillis());
                campRankListModel.rankChange(new CampRank(entry.getKey(), entry.getValue(), time));
            }
        }

        for (Map.Entry<Integer, LinkedList<CrossChefDuel2Rank>> entry : rankList.entrySet()) {
            CrossChefDuel2RankListModel model = campUserRankMap.get(entry.getKey());
            model.setRankList(entry.getValue());
        }
    }

    public void uploadChefDuelScore(List<ChefDuelProto.CrossChefDuel2ScoreTemp> scoreList) {
        for (ChefDuelProto.CrossChefDuel2ScoreTemp temp : scoreList) {
            ChefDuelUpUser user = chefDuelMap.get(temp.getUserId());
            if(user != null && user.getCampId() > 0){
                //分数有变化才入库
                if(user.getRankIntegral() != temp.getScore()) {
                    user.setRankIntegral(temp.getScore());
                    user.setRankTime(temp.getTime());
                    synchronized (needUpdateUserList){
                        if(!needUpdateUserList.contains(user)){
                            needUpdateUserList.add(user);
                        }
                    }
                }
            }
        }
    }

    public void closeTable(long serverId, long playerId, int serDishId) {
        ChefDuelUpUser user = chefDuelMap.get(playerId);
        if(user != null){
            Map<Integer,ChefDuel2DishTable> userDishMap = chefDuelTableMap.get(playerId);
            if(userDishMap != null){
                ChefDuel2DishTable dishTable = userDishMap.get(serDishId);
                if(dishTable != null){
                    if(dishTable.getOverTime() != 0){
                        return;
                    }
                    if(dishTable.getUserId() != playerId){
                        return;
                    }
                    ChefDuel2TableReward eatTableRes = null;
                    ChefDuel2DishConfig chefDuel2DishConfig = CrossChefDuelActivityMgr.getDishCondfig(getActivityId(), dishTable.getDishId());
                    ChefDuel2Spoon chefDuel2Spoon = CrossChefDuelActivityMgr.getChefDuel2MinSpoon(getActivityId());
                    if(chefDuel2DishConfig == null){
                        logger.error("厨神对决2找不到配置的菜品id"+ dishTable.getDishId());
                        return;
                    }
                    synchronized (dishTable) {
                        //时间到了结束//座位坐满了结束//每天到了晚上22点也结束
                        if(dishTable.getOverTime() == 0){
                            eatTableRes = endTable(dishTable);
                        }else {
                            return;
                        }
                    }
                    ChefDuelProto.ChefDuel2CloseTableRespMsg.Builder clientMsg = ChefDuelProto.ChefDuel2CloseTableRespMsg.newBuilder();
                    clientMsg.setRet(0);
                    clientMsg.setAddIntegral(eatTableRes.getIntegral());
                    clientMsg.setDishNum(1);
                    clientMsg.setSpoonId(chefDuel2Spoon.getItemId());
                    clientMsg.setSpoonNum(eatTableRes.getSeatNum());
                    MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_CLOSE_SERVE_DISH, clientMsg));
                    //把机器人的积分也同步下去，不然客户端刷新不准，会等通知积分通知本服，本服触发condition，再到跨服排行，才有他的积分
                    syncTableServers(playerId, Collections.singletonList(dishTable), eatTableRes.getIntegral());
                    synchronized (needSyncUserList){
                        if(!needSyncUserList.contains(chefDuelMap.get(playerId))){
                            needSyncUserList.add(chefDuelMap.get(playerId));
                        }
                    }
                }
            }
        }
    }

    public void closeAllTable(long serverId, long playerId) {
        ChefDuelUpUser user = chefDuelMap.get(playerId);
        if(user != null){
            Map<Integer,ChefDuel2DishTable> userDishMap = chefDuelTableMap.get(playerId);
            if(userDishMap != null){
                List<ChefDuel2DishTable> closeList = new ArrayList<>();
                long addTotal = 0;
                int totalSpoonId = 0;
                int seatNum = 0;
                int count = 0;
                for (Map.Entry<Integer, ChefDuel2DishTable> tableEntry : userDishMap.entrySet()) {
                    ChefDuel2DishTable dishTable = tableEntry.getValue();
                    if(dishTable.getOverTime() != 0){
                        continue;
                    }
                    if(dishTable.getUserId() != playerId){
                        continue;
                    }
                    ChefDuel2TableReward eatTableRes = null;
                    ChefDuel2DishConfig chefDuel2DishConfig = CrossChefDuelActivityMgr.getDishCondfig(getActivityId(), dishTable.getDishId());
                    ChefDuel2Spoon chefDuel2Spoon = CrossChefDuelActivityMgr.getChefDuel2MinSpoon(getActivityId());
                    if(chefDuel2DishConfig == null){
                        logger.error("厨神对决2找不到配置的菜品id"+ dishTable.getDishId());
                        continue;
                    }
                    synchronized (dishTable) {
                        //时间到了结束//座位坐满了结束//每天到了晚上22点也结束
                        if(dishTable.getOverTime() == 0){
                            eatTableRes = endTable(dishTable);
                        }else {
                            continue;
                        }
                    }
                    synchronized (needSyncUserList){
                        if(!needSyncUserList.contains(chefDuelMap.get(playerId))){
                            needSyncUserList.add(chefDuelMap.get(playerId));
                        }
                    }
                    addTotal += eatTableRes.getIntegral();
                    closeList.add(dishTable);
                    totalSpoonId = chefDuel2Spoon.getItemId();
                    seatNum += eatTableRes.getSeatNum();
                    count++;
                }
                if(count == 0){
                    ChefDuelProto.ChefDuel2CloseTableRespMsg.Builder clientMsg = ChefDuelProto.ChefDuel2CloseTableRespMsg.newBuilder();
                    clientMsg.setRet(GameErrorCode.E_CHEF_DUEL2_NO_TABLE_OPEN);
                    MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_CLOSE_SERVE_DISH_ONE_KEY, clientMsg));
                    return;
                }
                ChefDuelProto.ChefDuel2CloseTableRespMsg.Builder clientMsg = ChefDuelProto.ChefDuel2CloseTableRespMsg.newBuilder();
                clientMsg.setRet(0);
                clientMsg.setAddIntegral(addTotal);
                clientMsg.setSpoonId(totalSpoonId);
                clientMsg.setDishNum(count);
                clientMsg.setSpoonNum(seatNum);
                MessageHelper.sendPacket(serverId, playerId, YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_CLOSE_SERVE_DISH_ONE_KEY, clientMsg));
                //把机器人的积分也同步下去，不然客户端刷新不准，会等通知积分通知本服，本服触发condition，再到跨服排行，才有他的积分
                syncTableServers(playerId, closeList, addTotal);
            }
        }
    }

    public int getChefDuel2CampRank(long serverId, long playerId) {
        ChefDuelUpUser userData = chefDuelMap.get(playerId);
        if (userData == null || userData.getCampId() <= 0) {
            return GameErrorCode.E_CHEF_DUEL2_USER_NOT_ABLE;
        }
        synchronized (getUserLocker(playerId)) {
            if(userData.getCampRewardGet() == 1){
                return GameErrorCode.E_ACTIVITY_REWARD_IS_GET;
            }
            userData.setCampRewardGet(1);
            int myRank = -1;
            int num = 0;
            for (CampRank rank : campRankListModel.getRankList()) {
                num++;
                if (rank.getId() == userData.getCampId()) {
                    myRank = num;
                    break;
                }
            }
            ChefDuelProto.CrossChefDuelGetCampRankRewardRespMsg.Builder builder = ChefDuelProto.CrossChefDuelGetCampRankRewardRespMsg.newBuilder();
            builder.setRet(0);
            builder.setActivityId(getActivityInfo().getActivityId());
//            builder.setConditionType(eGamePlayerEventType.ChefDuel2CrossCampRank.getValue());
            builder.setRank(myRank);
            sendPacket(serverId, Protocol.S_CHEF_DUEL2_CAMP_RANK_REWARD_FROM_CROSS, builder, playerId);
        }
        synchronized (needUpdateUserList){
            if(!needUpdateUserList.contains(userData)){
                needUpdateUserList.add(userData);
            }
        }
        return 0;
    }

    protected void sendPacket(long serverId, int code, AbstractMessage.Builder<?> messageBuilder, long userId) {
        YanQuMessage message = YanQuMessageUtils.buildMessage(code, messageBuilder);
        MessageHelper.sendPacket(serverId, userId, message);
    }

    //补发阵营奖励
    public void sendCampRankReward() {
        List<ChefDuelUpUser> list = new ArrayList<>();
        for (Map.Entry<Long, ChefDuelUpUser> entry : chefDuelMap.entrySet()) {
            ChefDuelUpUser upUser = entry.getValue();
            if(upUser.getCampId() <= 0){
                continue;
            }
            if(upUser.getCampRewardGet() == 1){
                continue;
            }
            upUser.setCampRewardGet(1);
            list.add(upUser);
        }

        if(!list.isEmpty()){
            synchronized (needUpdateUserList){
                needUpdateUserList.addAll(list);
            }
            Map<Long, Map<Integer, Set<Long>>> serverRankListMap = new HashMap<>();
            for (ChefDuelUpUser upUser : list) {
                if(!serverRankListMap.containsKey(upUser.getServerId())){
                    serverRankListMap.put(upUser.getServerId(), new HashMap<>());
                }
                int myRank = campRankListModel.getMyRank(upUser.getCampId());
                if(!serverRankListMap.get(upUser.getServerId()).containsKey(myRank)){
                    serverRankListMap.get(upUser.getServerId()).put(myRank, new HashSet<>());
                }
                serverRankListMap.get(upUser.getServerId()).get(myRank).add(upUser.getUserId());
            }
            if(!serverRankListMap.isEmpty()){
                for (Map.Entry<Long, Map<Integer, Set<Long>>> entry : serverRankListMap.entrySet()) {
                    ChefDuelProto.CrossChefDuelCampRewardSendMsg.Builder msg = ChefDuelProto.CrossChefDuelCampRewardSendMsg.newBuilder();
                    msg.setActivityId(activityInfo.getActivityId());
                    for (Map.Entry<Integer, Set<Long>> setEntry : entry.getValue().entrySet()) {
                        ChefDuelProto.ChefDuelCampRewardTemp.Builder builder = ChefDuelProto.ChefDuelCampRewardTemp.newBuilder();
                        builder.setRank(setEntry.getKey());
                        builder.addAllUserId(setEntry.getValue());
                        builder.setReward(CrossChefDuelActivityMgr.getChefDuel2CampReward(activityInfo.getActivityId(), setEntry.getKey()));
                        msg.addRank(builder);
                    }
                    MessageHelper.sendPacket(entry.getKey(), 0, YanQuMessageUtils.buildMessage(Protocol.S_CHEF_DUEL2_CAMP_REWARD_SEND_FROM_CROSS, msg));
                }
            }
        }
    }

    //从大到小
    static class CookerSort implements Comparator<ChefDuelUpUser> {
        @Override
        public int compare(ChefDuelUpUser o1, ChefDuelUpUser o2) {
            if (o1.getIntegral() == o2.getIntegral()) {
                return 0;
            }
            if (o1.getIntegral() <= o2.getIntegral()) {
                return 1;
            }
            return -1;
        }
    }

    //同步每一个参赛者可吃可不吃状态
    public void syncCookerServer(){
//        logger.error("同步数据数目"+needSyncUserList.size());
        List<ChefDuelUpUser> tempList;
        synchronized (needSyncUserList) {
            tempList = new ArrayList<>(needSyncUserList);
            needSyncUserList.clear();
        }
        if (tempList.isEmpty()) {
            return;
        }
        ChefDuelProto.CrossChefDuel2CookerSyncMsg.Builder respMsg = ChefDuelProto.CrossChefDuel2CookerSyncMsg.newBuilder();
        respMsg.setActivityId(getActivityId());
        for(ChefDuelUpUser chefDuelUpUser : tempList){
            ChefDuelProto.CrossChefDuel2CookerTempMsg.Builder userMsg = ChefDuelProto.CrossChefDuel2CookerTempMsg.newBuilder();
            userMsg.setServerId(chefDuelUpUser.getServerId());
            userMsg.setUserId(chefDuelUpUser.getUserId());
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(chefDuelUpUser.getUserId());
            if(userBaseInfo == null){
                continue;
            }
            userMsg.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
            List<Long> noEatUserIdList = getCookerNoEatUserIdList(chefDuelUpUser.getUserId());
            if(noEatUserIdList == null){
                userMsg.setCanEat(false);
            }else{
                userMsg.setCanEat(true);
                userMsg.addAllNoEatUserId(noEatUserIdList);
            }
            userMsg.setRank(chefDuelUpUser.getRank());
            respMsg.addCookerList(userMsg);
        }
        for(long serverId : activityInfo.getServerIdList2()){
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_COOKER_SYNC, respMsg);
            MessageHelper.sendPacket(serverId, 0, pbMsg);
        }
    }

    private ChefDuel2DishTable initChefDuel2DishTable(long serverId,long userId,int id,int dishId,int no){
        ChefDuel2DishTable newOne = new ChefDuel2DishTable();
        newOne.setActivityId(activityInfo.getActivityId());
        newOne.setServerId(serverId);
        newOne.setUserId(userId);
        newOne.setUserDishId(id);
        newOne.setDishId(dishId);
        newOne.setOpenTime(System.currentTimeMillis());
        newOne.setOverTime(0);
        newOne.setIntegral(0);
        newOne.setJoinerData("{}");
        newOne.setNo(no);

        return newOne;
    }

    public List<Integer> getUserForbiddenSpoonIdList(long userId){
        ChefDuelUpUser cookData = chefDuelMap.get(userId);
        List<Integer> forbidSpoonIdList = new ArrayList<>();
        if(cookData != null){
            forbidSpoonIdList = cookData.getForbiddenSpoonList();
        }
        return forbidSpoonIdList;
    }

    private Map<Long, Object> userLockerMap = new ConcurrentHashMap<>();

    public Object getUserLocker(long userId){
        if(!userLockerMap.containsKey(userId)){
            synchronized (userLockerMap){
                if(!userLockerMap.containsKey(userId)){
                    userLockerMap.put(userId, new Object());
                }
            }
        }
        return userLockerMap.get(userId);
    }

    public int preJoinTable(long serverId, long joinUserId, long homeUserId, int tableId, int spoonId, int trueActivityId, int campId){
        int reason = 0;
        //判断我方是否满座
        Map<Integer, ChefDuel2DishTable> dishTableMap = openChefDuelTableMap.get(joinUserId);
        if(dishTableMap == null || dishTableMap.isEmpty()){
            reason = 2;
        }else {
            boolean canEat = false;
            for (Map.Entry<Integer, ChefDuel2DishTable> entry : dishTableMap.entrySet()) {
                ChefDuel2DishTable value = entry.getValue();
                if(!value.getChefDuel2JoinerMap().containsKey(homeUserId)){
                    canEat = true;
                    break;
                }
            }
            if(!canEat){
                reason = 2;
            }
            if(reason == 0){
                //我方金筷子次数上限
                ChefDuelUpUser chefDuelUpUser = chefDuelMap.get(joinUserId);
                if(chefDuelUpUser.getSpoonLimit() >= CrossChefDuelActivityMgr.getChefDuel2SpoonLimit(activityInfo.getActivityId(), spoonId)){
                    reason = 3;
                }
            }
        }
        //对方是否有设置回宴
        if(reason == 0) {
            if (trueActivityId == activityInfo.getActivityId()) {
                CrossChefDuel2AutoJoinSpoon autoJoinSpoon = autoJoinSpoonMap.get(homeUserId);
                if(autoJoinSpoon == null){
                    reason = 1;
                }else {
                    int integer = autoJoinSpoon.getSpoonMap().getOrDefault(spoonId, 0);
                    if(integer <= 0){
                        reason = 1;
                    }
                }
            }else {
                //对方是否有设置回宴
                ChefDuelProto.ChefDuel2PreJoinTableReqMsg.Builder reqMsg = ChefDuelProto.ChefDuel2PreJoinTableReqMsg.newBuilder();
                reqMsg.setActivityId(trueActivityId);
                reqMsg.setUserId(homeUserId);
                reqMsg.setTableId(tableId);
                reqMsg.setSpoonId(spoonId);
                reqMsg.setOtherActivityId(activityInfo.getActivityId());
                reqMsg.setCampId(campId);
                YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.C_CROSS_CHEF_DUEL2_PRE_JOIN_OTHER_TABLE, reqMsg);
                MessageHelper.sendPacket(serverId, joinUserId, pbMsg);
                return 0;
            }
        }
        //返回客户端
        ChefDuelProto.ChefDuel2PreJoinTableRespMsg.Builder clientMsg = ChefDuelProto.ChefDuel2PreJoinTableRespMsg.newBuilder();
        clientMsg.setRet(0);
        clientMsg.setReason(reason);
        YanQuMessage yanQuMessage = YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_PRE_JOIN_TABLE, clientMsg);
        MessageHelper.sendPacket(serverId, joinUserId, yanQuMessage);
        return 0;
    }

    public int preJoinOtherTable(long serverId, long joinUserId, long homeUserId, int tableId, int spoonId, int trueActivityId, int campId){
        int reason = 0;
        //对方是否有设置回宴
        CrossChefDuel2AutoJoinSpoon autoJoinSpoon = autoJoinSpoonMap.get(homeUserId);
        if(autoJoinSpoon == null){
            reason = 1;
        }else {
            int integer = autoJoinSpoon.getSpoonMap().getOrDefault(spoonId, 0);
            if(integer <= 0){
                reason = 1;
            }
        }
        //返回客户端
        ChefDuelProto.ChefDuel2PreJoinTableRespMsg.Builder clientMsg = ChefDuelProto.ChefDuel2PreJoinTableRespMsg.newBuilder();
        clientMsg.setRet(0);
        clientMsg.setReason(reason);
        YanQuMessage yanQuMessage = YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_PRE_JOIN_TABLE, clientMsg);
        MessageHelper.sendPacket(serverId, joinUserId, yanQuMessage);
        return 0;
    }

    public int joinTable(long serverId, long joinUserId, long homeUserId, int tableId, int spoonId, int trueActivityId, int campId){
        if(!chefDuelTableMap.containsKey(homeUserId)){
            return GameErrorCode.E_CHEF_DUEL2_TABLE_NOT_FOUND;
        }
        Map<Integer,ChefDuel2DishTable> chefDuel2DishTableMap = chefDuelTableMap.get(homeUserId);
        if(!chefDuel2DishTableMap.containsKey(tableId)){
            return GameErrorCode.E_CHEF_DUEL2_TABLE_NOT_FOUND;
        }
        ChefDuel2Spoon chefDuel2Spoon = CrossChefDuelActivityMgr.getChefDuel2Spoon(getActivityId(),spoonId);
        if(chefDuel2Spoon == null){
            return GameErrorCode.E_CHEF_DUEL2_SPOON_NOT_FOUND;
        }
        ChefDuel2DishTable chefDuel2DishTable = chefDuel2DishTableMap.get(tableId);

        ChefDuel2DishConfig chefDuel2DishConfig = CrossChefDuelActivityMgr.getDishCondfig(getActivityId(),chefDuel2DishTable.getDishId());
        if(chefDuel2DishConfig == null){
            return GameErrorCode.E_CHEF_DUEL2_DISH_CONFIG_NOT_FOUND;
        }
        ChefDuelUpUser cookData = chefDuelMap.get(homeUserId);
        List<Integer> forbidSpoonIdList = new ArrayList<>();
        if(cookData != null){
            forbidSpoonIdList = cookData.getForbiddenSpoonList();
            if(forbidSpoonIdList.contains(spoonId)){
                return GameErrorCode.E_CHEF_DUEL2_EAT_SPOON_FORBID;
            }
        }
        if(cookData == null){
            return GameErrorCode.E_CHEF_DUEL2_USER_NOT_ABLE;
        }

        synchronized (getUserLocker(homeUserId)){
            //金制厨神筷子数量限制
            if(cookData.getSpoonLimit() >= CrossChefDuelActivityMgr.getChefDuel2SpoonLimit(activityInfo.getActivityId(), spoonId)){
                return GameErrorCode.E_CHEF_DUEL2_SPOON_LIMIT;
            }
            synchronized (chefDuel2DishTable) {
                if(chefDuel2DishTable.getOverTime() != 0){
                    return GameErrorCode.E_CHEF_DUEL2_TABLE_OVER;
                }
                if(chefDuel2DishTable.getChefDuel2JoinerMap().size() >= chefDuel2DishConfig.getSeat()){
                    return GameErrorCode.E_CHEF_DUEL2_TABLE_SEAT_FULL;
                }
                if(!CrossChefDuelActivityMgr.isActivityMatchTime(activityInfo)){
                    return GameErrorCode.E_CHEF_DUEL2_ACTIVITY_NOT_RUNNING;
                }
                Map<Long, ChefDuel2Joiner> joinerMap = chefDuel2DishTable.getChefDuel2JoinerMap();
                if(joinerMap.containsKey(joinUserId)){
                    return GameErrorCode.E_CHEF_DUEL2_TABLE_IS_JOIN;
                }
                ChefDuel2Joiner chefDuel2Joiner = new ChefDuel2Joiner();
                chefDuel2Joiner.setServerId(serverId);
                chefDuel2Joiner.setUserId(joinUserId);
                chefDuel2Joiner.setGifttId(spoonId);
                chefDuel2Joiner.setPos(joinerMap.size() + 1);
                joinerMap.put(chefDuel2Joiner.getUserId(),chefDuel2Joiner);
                chefDuel2DishTable.setChefDuel2JoinerMap(joinerMap);
                chefDuel2DishTable.setIntegral(chefDuel2DishTable.getIntegral() + chefDuel2Spoon.getUserIntegral());

                int chefDuel2SpoonLimit = CrossChefDuelActivityMgr.getChefDuel2SpoonLimit(activityInfo.getActivityId(), spoonId);
                if(chefDuel2SpoonLimit < Integer.MAX_VALUE) {
                    cookData.setSpoonLimit(cookData.getSpoonLimit() + 1);
                }
            }
            synchronized (needUpdateUserList){
                if(!needUpdateUserList.contains(cookData)){
                    needUpdateUserList.add(cookData);
                }
            }
            //试吃日志
            CrossAutoLogMgr.add(new LogChefDuel2East(chefDuel2DishTable.getActivityId(),
                    joinUserId,
                    campId,
                    cookData.getUserId(),
                    cookData.getCampId(),
                    joinUserId == homeUserId ? chefDuel2Spoon.getUserIntegral() + chefDuel2Spoon.getJoinerIntegral() : chefDuel2Spoon.getJoinerIntegral(),
                    tableId,
                    spoonId + "=1",
                    chefDuel2DishTable.getDishId(),
                    trueActivityId));
        }

        ChefDuelProto.CrossChefDuel2JoinTableMsg.Builder joinMsg = ChefDuelProto.CrossChefDuel2JoinTableMsg.newBuilder();
        joinMsg.setRet(0);
        joinMsg.setActivityId(getActivityId());
        joinMsg.setJoinerUserId(joinUserId);
        joinMsg.setHomeUserId(homeUserId);
        joinMsg.setTableId(tableId);
        joinMsg.setSpoonId(spoonId);
        joinMsg.addAllForbidSpoonId(forbidSpoonIdList);
        if(trueActivityId > 0){
            joinMsg.setActivityId(trueActivityId);
            joinMsg.setOtherActivityId(getActivityId());
        }
        YanQuMessage pbJoinerMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_JOIN_JOINER, joinMsg);

        ChefDuelProto.CrossChefDuel2JoinTableMsg.Builder msg = ChefDuelProto.CrossChefDuel2JoinTableMsg.newBuilder();
        msg.setRet(0);
        msg.setActivityId(getActivityId());
        msg.setJoinerUserId(joinUserId);
        msg.setHomeUserId(homeUserId);
        msg.setTableId(tableId);
        msg.setSpoonId(spoonId);
        msg.addAllForbidSpoonId(forbidSpoonIdList);
        YanQuMessage pbOpenerMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_JOIN_OPENER, msg);
        MessageHelper.sendPacket(serverId, joinUserId, pbJoinerMsg);
        MessageHelper.sendPacket(chefDuel2DishTable.getServerId(), homeUserId, pbOpenerMsg);
        newJoin(homeUserId,joinUserId, trueActivityId);
        //自己加入自己
        if(joinUserId == homeUserId){
            syncTableServer(chefDuel2DishTable,chefDuel2Spoon.getUserIntegral() + chefDuel2Spoon.getJoinerIntegral());
        }else{
            syncTableServer(chefDuel2DishTable,chefDuel2Spoon.getUserIntegral());
        }
        tableCheck();
        synchronized (needUpdateTableList){
            if (!needUpdateTableList.contains(chefDuel2DishTable)) {
                needUpdateTableList.add(chefDuel2DishTable);
            }
        }
        synchronized (needSyncUserList){
            if (!needSyncUserList.contains(chefDuelMap.get(homeUserId))) {
                needSyncUserList.add(chefDuelMap.get(homeUserId));
            }
        }


        if (joinUserId != homeUserId) { // 不能回访自己，自动回访中摊主和访客的身份互换
            UserBaseInfo hostInfo = CrossUserMgr.getUserBaseInfo(homeUserId);
            if (hostInfo != null) {
                ChefDuelProto.CrossChefDuel2AutoJoinInfoMsg.Builder req = ChefDuelProto.CrossChefDuel2AutoJoinInfoMsg.newBuilder();
                req.setHostActivityId(trueActivityId);
                req.setGuestActivityId(getActivityId());
                req.setHostId(joinUserId);
                req.setGuestId(homeUserId);
                req.setSpoonId(spoonId);
                req.setHostServerId(serverId);
                YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_AUTO_JOIN, req);
                MessageHelper.sendPacket(hostInfo.getServerId(), homeUserId, pbMsg);
            }
        }

        return 0;
    }

    public void newJoin(long homeUserId, long joinUserId, int trueActivityId){
        /*if(homeUserId == joinUserId)return;
        synchronized (joinMap){
            long userId1,userId2;
            if(homeUserId > joinUserId){
                userId1 = homeUserId;
                userId2 = joinUserId;
            }else{
                userId1 = joinUserId;
                userId2 = homeUserId;
            }
            if(!joinMap.containsKey(userId1)){
                ChefDuel2UserJoinData newOne = new ChefDuel2UserJoinData();
                newOne.setActivityId(getActivityId());
                newOne.setUserId1(userId1);
                newOne.setUserId2(userId2);
                newOne.setJoinTime1(userId1==joinUserId?1:0);
                newOne.setJoinTime2(userId2==joinUserId?1:0);
                newOne.setLastJoinTime(System.currentTimeMillis());
                joinList.add(newOne);
                joinMap.put(userId1,newOne);
                joinInsertList.add(newOne);
            }else{
                ChefDuel2UserJoinData temp = joinMap.get(userId1);
                temp.setJoinTime1(temp.getJoinTime1()+(userId1==joinUserId?1:0));
                temp.setJoinTime2(temp.getJoinTime2()+(userId2==joinUserId?1:0));
                temp.setLastJoinTime(System.currentTimeMillis());
                if(!joinUpdateList.contains(temp)){
                    joinUpdateList.add(temp);
                }
            }
        }*/
        long userId1,userId2;
        if(homeUserId > joinUserId){
            userId1 = homeUserId;
            userId2 = joinUserId;
        }else{
            userId1 = joinUserId;
            userId2 = homeUserId;
        }
        boolean isFind = false;
        for(ChefDuel2UserJoinData chefDuel2UserJoinData : joinList){
            if(chefDuel2UserJoinData.getActivityId() == getActivityId() && chefDuel2UserJoinData.getUserId1() == userId1 && chefDuel2UserJoinData.getUserId2() == userId2){
                chefDuel2UserJoinData.setJoinTime1(chefDuel2UserJoinData.getJoinTime1()+(userId1==joinUserId?1:0));
                chefDuel2UserJoinData.setJoinTime2(chefDuel2UserJoinData.getJoinTime2()+(userId2==joinUserId?1:0));
                chefDuel2UserJoinData.setLastJoinTime(System.currentTimeMillis());
                synchronized (joinUpdateList){
                    if(!joinUpdateList.contains(chefDuel2UserJoinData)){
                        joinUpdateList.add(chefDuel2UserJoinData);
                    }
                }
                isFind = true;
                break;
            }
        }
        if(!isFind){
            ChefDuel2UserJoinData newOne = new ChefDuel2UserJoinData();
            newOne.setActivityId(getActivityId());
            newOne.setUserId1(userId1);
            newOne.setUserId2(userId2);
            newOne.setJoinTime1(userId1==joinUserId?1:0);
            newOne.setJoinTime2(userId2==joinUserId?1:0);
            newOne.setLastJoinTime(System.currentTimeMillis());
            newOne.setOtherActivityId(trueActivityId);
            synchronized (joinList){
                joinList.add(newOne);
            }
            synchronized (joinInsertList){
                joinInsertList.add(newOne);
            }
        }

    }

    private int getTableCount(){
        int count = 0;
        for(Map<Integer, ChefDuel2DishTable> userMap : chefDuelTableMap.values()){
            count += userMap.size();
        }
        return count;
    }

    //是否已经上过了
    private boolean isDishEat(long userId,int userDishId){
        Map<Integer, ChefDuel2DishTable> userTableMap = chefDuelTableMap.get(userId);
        for(ChefDuel2DishTable chefDuel2DishTable : userTableMap.values()){
            if(chefDuel2DishTable.getUserDishId() == userDishId){
                return true;
            }
        }
        return false;
    }

    public void serveDish(long serverId,long userId,Map<Integer,Integer> dishMap){
        tableCheck();
        ChefDuelProto.ChefDuel2OpenTableRespMsg.Builder msg = ChefDuelProto.ChefDuel2OpenTableRespMsg.newBuilder();
        msg.setActivityId(getActivityId());
        int ret = 0;
        if(!chefDuelTableMap.containsKey(userId)){
            chefDuelTableMap.put(userId,new ConcurrentHashMap<>());
        }
        Map<Integer, ChefDuel2DishTable> userTableMap = chefDuelTableMap.get(userId);
        if(getUserOpenDishTables(userId).size() + dishMap.size() > CrossChefDuelActivityMgr.getChefDuel2OpenTableLimit(activityInfo.getActivityId())){
            ret = GameErrorCode.E_CHEF_DUEL2_DISH_OPEN_LIMIT;
        }
        for(int userDishId : dishMap.keySet()){
            if(isDishEat(userId,userDishId)){
                ret = GameErrorCode.E_CHEF_DUEL2_DISH_IS_SERVE;
                break;
            }
        }
        if(ret != 0){
            msg.setRet(ret);
            //上了那些菜给他改回来状态
            for(int userDishId : dishMap.keySet()) {
                ChefDuelProto.CrossChefDuel2FoodTableIdMsg.Builder foodTableMsg = ChefDuelProto.CrossChefDuel2FoodTableIdMsg.newBuilder();
                foodTableMsg.setUserDishId(userDishId);
                foodTableMsg.setTableId(0);
                msg.addFoodList(foodTableMsg);
            }
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_SERVE_DISH, msg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
            return;
        }
        List<ChefDuel2DishTable> syncList = new ArrayList<>();
        for(int userDishId : dishMap.keySet()){
            ChefDuel2DishTable newOne = initChefDuel2DishTable(serverId,userId,userDishId,dishMap.get(userDishId), getTableCount() + 1);
            chefDuelTableMap.get(userId).put(newOne.getNo(),newOne);
            addOpenTable(newOne);
            synchronized (needInsertTableList){
                if(!needInsertTableList.contains(newOne)){
                    needInsertTableList.add(newOne);
                }
            }
            syncList.add(newOne);
            ChefDuelProto.CrossChefDuel2FoodTableIdMsg.Builder foodTableMsg = ChefDuelProto.CrossChefDuel2FoodTableIdMsg.newBuilder();
            foodTableMsg.setUserDishId(userDishId);
            foodTableMsg.setTableId(newOne.getNo());
            msg.addFoodList(foodTableMsg);
        }
        synchronized (needSyncUserList){
            if (!needSyncUserList.contains(chefDuelMap.get(userId))) {
                needSyncUserList.add(chefDuelMap.get(userId));
            }
        }
        //同步所有区服有人开了
        syncTableServers(userId,syncList,0);
        //开宴立即同步一次
        syncCookerServer();

        msg.setRet(ret);
        /*ChefDuelProto.ChefDuel2UserIdTableRespMsg.Builder tableMsg = getTablesMsg(serverId,userId,0,0);
        msg.setSelfTable(tableMsg);*/
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_SERVE_DISH, msg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    //获取用户开的宴会上的桌子，正在进行中的
    private Map<Integer,ChefDuel2DishTable> getUserOpenDishTables(long userId){
        Map<Integer,ChefDuel2DishTable> res = new ConcurrentHashMap<>();
        if(!chefDuelTableMap.containsKey(userId)){
            return res;
        }
        for(ChefDuel2DishTable temp : chefDuelTableMap.get(userId).values()){
            if(temp.getOverTime() == 0){
                res.put(temp.getNo(),temp);
            }
        }
        return res;
    }
    private Map<Integer,ChefDuel2DishTable> getUserDishTables(long userId,int page,int num){
        Map<Integer,ChefDuel2DishTable> res = new ConcurrentHashMap<>();
        if(!chefDuelTableMap.containsKey(userId)){
            return res;
        }
        List<ChefDuel2DishTable> chefDuel2DishTableList = new ArrayList<>(chefDuelTableMap.get(userId).values());
        chefDuel2DishTableList.sort(new TableSort());
        int count = chefDuel2DishTableList.size();
        int index = (page - 1) * num;
        int resCount = 0;
        for(;index < count + num;index++){
            if(resCount++ == num){
                break;
            }
            if(chefDuel2DishTableList.size() > index){
                ChefDuel2DishTable temp = chefDuel2DishTableList.get(index);
                res.put(temp.getNo(),temp);
            }else{
                break;
            }
        }
        return res;
    }
    //从大
    static class TableSort implements Comparator<ChefDuel2DishTable> {
        @Override
        public int compare(ChefDuel2DishTable o1, ChefDuel2DishTable o2) {
            if (o1.getNo() == o2.getNo()) {
                return 0;
            }
            if (o1.getNo() < o2.getNo()) {
                return 1;
            }
            return -1;
        }
    }

    private ChefDuelProto.ChefDuel2UserIdTableRespMsg.Builder getTablesMsg(long serverId, long homeUserId,int page,int num){
        if(page == 0){
            page = 1;
        }
        if(num == 0 || num > 50){
            num = 50;
        }
        Map<Integer,ChefDuel2DishTable> tableMap = getUserDishTables(homeUserId,page,num);
        int dishNum = 0;
        if(chefDuelTableMap.containsKey(homeUserId)){
            dishNum = chefDuelTableMap.get(homeUserId).size();
        }
        ChefDuelProto.ChefDuel2UserIdTableRespMsg.Builder respMsg = CrossChefDuelPb.parseChefDuel2CookerTableRespMsg(tableMap,getActivityId(),serverId,homeUserId,dishNum,0);
        for(Integer spoonId : chefDuelMap.get(homeUserId).getForbiddenSpoonList()){
            respMsg.addForbidSpoonId(spoonId);
        }
        CrossChefDuel2AutoJoinSpoon autoJoinSpoon = autoJoinSpoonMap.get(homeUserId);
        if(autoJoinSpoon != null){
            for (Map.Entry<Integer, Integer> entry : autoJoinSpoon.getSpoonMap().entrySet()) {
                respMsg.addSettingSpoon(ChefDuelProto.ChefDuel2SettingSpoon.newBuilder().setSpoonId(entry.getKey()).setSpoonNum(entry.getValue()));
            }
        }
        CrossChefDuelActivityMgr.setGoldEastLimit(homeUserId, respMsg, activityInfo.getActivityId());
        return respMsg;
    }

    public void syncCookerHomeTable(long serverId,long userId,long homeUserId,int page,int num){
        tableCheck();
        ChefDuelProto.ChefDuel2UserIdTableRespMsg.Builder respMsg = getTablesMsg(chefDuelMap.get(homeUserId).getServerId(),homeUserId,page,num);
        if(respMsg != null){
            respMsg.setIsSync(false);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_GET_TABLE_INFO, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
        }
    }

    public void getCookerTable(long serverId,long userId,long homeUserId,int tableId){
        ChefDuel2DishTable chefDuel2DishTable = null;
        if(chefDuelTableMap.containsKey(homeUserId) && chefDuelTableMap.get(homeUserId).containsKey(tableId)){
            chefDuel2DishTable = chefDuelTableMap.get(homeUserId).get(tableId);
        }
        ChefDuelProto.ChefDuel2UserTableInfoRespMsg.Builder respMsg = CrossChefDuelPb.parseChefDuel2RecordRespMsg(chefDuel2DishTable);
        if(respMsg != null){
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_USER_TABLE_INFO_REQ, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
        }
    }

    public void syncCookerTable(long serverId,long userId){
//        cookerRanking();
        tableCheck();
        ChefDuelProto.ChefDuel2CookerRespMsg.Builder respMsg = ChefDuelProto.ChefDuel2CookerRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setActivityId(activityInfo.getActivityId());
        for(ChefDuelUpUser chefDuel2User : chefDuelMap.values()){
            //自己的玩家数据还是得下发
            if(chefDuel2User.getCampId() <= 0 && chefDuel2User.getUserId() != userId){
                continue;
            }
            ChefDuelProto.ChefDuel2CookerTempMsg.Builder tempFoodMsg = ChefDuelProto.ChefDuel2CookerTempMsg.newBuilder();
            tempFoodMsg.setServerId(chefDuel2User.getServerId());
            tempFoodMsg.setUserId(chefDuel2User.getUserId());
            tempFoodMsg.setCanEat(isOpenTableCanEat(chefDuel2User.getUserId(),userId));
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(chefDuel2User.getUserId());
            if(userBaseInfo == null){
                continue;
            }
            tempFoodMsg.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
            tempFoodMsg.setRank(chefDuel2User.getRank());
            tempFoodMsg.setCampId(chefDuel2User.getCampId());
            tempFoodMsg.setActivityId(activityInfo.getActivityId());
            respMsg.addCookerList(tempFoodMsg);
        }
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_GET_TABLE_USER, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    private boolean isOpenTableCanEat(long userId,long joinUserId){
        if(chefDuelTableMap.containsKey(userId)){
            Map<Integer, ChefDuel2DishTable> tempMap = chefDuelTableMap.get(userId);
            for(ChefDuel2DishTable chefDuel2DishTable : tempMap.values()){
                ChefDuel2DishConfig chefDuel2DishConfig = CrossChefDuelActivityMgr.getDishCondfig(getActivityId(),chefDuel2DishTable.getDishId());
                if(chefDuel2DishTable.getOverTime() == 0 && chefDuel2DishTable.getChefDuel2JoinerMap().size() < chefDuel2DishConfig.getSeat()){
                    if(!chefDuel2DishTable.getChefDuel2JoinerMap().containsKey(joinUserId)){
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public void getRecord(long serverId,long userId){
        tableCheck();
        ChefDuelProto.ChefDuel2RecordRespMsg.Builder respMsg = ChefDuelProto.ChefDuel2RecordRespMsg.newBuilder();
        respMsg.setRet(0);
        for(ChefDuel2UserJoinData chefDuel2UserJoinData : new ArrayList<>(joinList)){
            if(chefDuel2UserJoinData.getUserId1() == userId && chefDuel2UserJoinData.getActivityId() ==getActivityId()){
                ChefDuelProto.BanquetRelationshipTemp.Builder temp = ChefDuelProto.BanquetRelationshipTemp.newBuilder();
                temp.setUserId(chefDuel2UserJoinData.getUserId2());
                temp.setTo(chefDuel2UserJoinData.getJoinTime1());
                temp.setFrom(chefDuel2UserJoinData.getJoinTime2());
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(chefDuel2UserJoinData.getUserId2());
                if(userBaseInfo != null){
                    temp.setPlayerBaseData(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                }
                temp.setBanquetId(isOpenTableCanEat(chefDuel2UserJoinData.getUserId2(),chefDuel2UserJoinData.getUserId1())?"1":"0");
                respMsg.addRecordList(temp);
            }else if(chefDuel2UserJoinData.getUserId2() == userId && chefDuel2UserJoinData.getActivityId() ==getActivityId()){
                ChefDuelProto.BanquetRelationshipTemp.Builder temp = ChefDuelProto.BanquetRelationshipTemp.newBuilder();
                temp.setUserId(chefDuel2UserJoinData.getUserId1());
                temp.setTo(chefDuel2UserJoinData.getJoinTime2());
                temp.setFrom(chefDuel2UserJoinData.getJoinTime1());
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(chefDuel2UserJoinData.getUserId1());
                if(userBaseInfo != null){
                    temp.setPlayerBaseData(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                }
                temp.setBanquetId(isOpenTableCanEat(chefDuel2UserJoinData.getUserId1(),chefDuel2UserJoinData.getUserId2())?"1":"0");
                respMsg.addRecordList(temp);
            }
        }
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_GET_JOIN_RECORD, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    //获取某个用户有几张桌子可以试吃
    private int getUserEatNum(long userId,long joinUserId){
        int count = 0;
        if(chefDuelTableMap.containsKey(userId)){
            Map<Integer, ChefDuel2DishTable> tableMap = chefDuelTableMap.get(userId);
            for(ChefDuel2DishTable chefDuel2DishTable : tableMap.values()){
                ChefDuel2DishConfig chefDuel2DishConfig = CrossChefDuelActivityMgr.getDishCondfig(getActivityId(),chefDuel2DishTable.getDishId());
                if(chefDuel2DishTable.getOverTime() == 0 && chefDuel2DishTable.getChefDuel2JoinerMap().size() <= chefDuel2DishConfig.getSeat()){
                    if(!chefDuel2DishTable.getChefDuel2JoinerMap().containsKey(joinUserId)){
                        count++;
                    }
                }
            }
        }
        return count;
    }

    public void getUnionRelation(long serverId,long playerId, List<Long> unionList,List<Long> relationList){
        tableCheck();
        ChefDuelProto.ChefDuel2SearchRespMsg.Builder respMsg = ChefDuelProto.ChefDuel2SearchRespMsg.newBuilder();
        respMsg.setRet(0);
        for(long unionUserId : unionList){
            ChefDuelProto.ChefDuel2SearchTempMsg.Builder temp = getSearchTempBuilder(playerId, unionUserId);
            if (temp != null) {
                respMsg.addUnionList(temp);
            }
        }
        for(long relationUserId : relationList){
            ChefDuelProto.ChefDuel2SearchTempMsg.Builder temp = getSearchTempBuilder(playerId, relationUserId);
            if (temp != null) {
                respMsg.addMarryList(temp);
            }
        }
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_SEARCH_REQ, respMsg);
        MessageHelper.sendPacket(serverId, playerId, pbMsg);
    }
    public void getSearchAll(long serverId,long playerId){
        tableCheck();
        ChefDuelProto.ChefDuel2SearchAllRespMsg.Builder respMsg = ChefDuelProto.ChefDuel2SearchAllRespMsg.newBuilder();
        respMsg.setRet(0);
        for (Map.Entry<Long, ChefDuelUpUser> upUserEntry : chefDuelMap.entrySet()) {
            if(upUserEntry.getValue().getCampId() <= 0){
                continue;
            }
            if(upUserEntry.getKey() == playerId){
                continue;
            }
            ChefDuelProto.ChefDuel2SearchTempMsg.Builder temp = getSearchTempBuilder(playerId, upUserEntry.getKey());
            if (temp != null && temp.getEatNum() > 0) {
                respMsg.addAllList(temp);
            }
        }

        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_SEARCH_REQ_CAN_EAST, respMsg);
        MessageHelper.sendPacket(serverId, playerId, pbMsg);
    }

    private ChefDuelProto.ChefDuel2SearchTempMsg.Builder getSearchTempBuilder(long playerId, long uid) {
        ChefDuelProto.ChefDuel2SearchTempMsg.Builder temp = ChefDuelProto.ChefDuel2SearchTempMsg.newBuilder();
        temp.setUserId(uid);
        temp.setEatNum(getUserEatNum(uid, playerId));
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(uid);
        if (userBaseInfo == null) {
            return null;
        }
        ChefDuelUpUser chefDuelUpUser = chefDuelMap.get(uid);
        if(chefDuelUpUser == null || chefDuelUpUser.getCampId() <= 0){
            return null;
        }
        temp.addAllSpoonId(getUserSettingSpoon(uid));
        temp.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
        return temp;
    }

    private List<Integer> getUserSettingSpoon(long uid) {
        CrossChefDuel2AutoJoinSpoon joinSpoon = autoJoinSpoonMap.get(uid);
        if(joinSpoon != null){
            List<Integer> list = new ArrayList<>();
            for (Map.Entry<Integer, Integer> entry : joinSpoon.getSpoonMap().entrySet()) {
                if(entry.getValue() > 0) {
                    list.add(entry.getKey());
                }
            }
            return list;
        }else {
            return Collections.emptyList();
        }
    }

    public void searchUser(long serverId,long userId,String searchUserId){
        tableCheck();
        ChefDuelProto.ChefDuel2SearchOneRespMsg.Builder respMsg = ChefDuelProto.ChefDuel2SearchOneRespMsg.newBuilder();
        respMsg.setRet(0);
        if(!StringUtils.isNumber(searchUserId)){
            respMsg.setRet(GameErrorCode.E_CHEF_DUEL2_USER_NOT_FUND);
        }
        UserBaseInfo selfUserInfo = CrossUserMgr.getUserBaseInfo(userId);
        if(selfUserInfo != null && StringUtils.isNumber(searchUserId) &&  selfUserInfo.getUserAliasId() == Long.valueOf(searchUserId)){
            respMsg.setRet(GameErrorCode.E_CHEF_DUEL2_SEARCH_USER_SELF);
        }
        if(respMsg.getRet() == 0){
            ChefDuelProto.ChefDuel2SearchTempMsg.Builder temp = null;
            for(Long homeUserId : new ArrayList<>(chefDuelMap.keySet())){
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(homeUserId);
                if(userBaseInfo == null){
                    continue;
                }
                if(userBaseInfo.getUserAliasId() ==  Long.parseLong(searchUserId)){
                    temp = ChefDuelProto.ChefDuel2SearchTempMsg.newBuilder();
                    temp.setUserId(homeUserId);
                    temp.setEatNum(getUserEatNum(homeUserId,userId));
                    temp.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                    temp.addAllSpoonId(getUserSettingSpoon(homeUserId));
                    respMsg.setSearchData(temp);
                    break;
                }
            }
            if(temp == null){
                respMsg.setRet(GameErrorCode.E_CHEF_DUEL2_USER_NOT_FUND);
            }
        }
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_SEARCH_ONE, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    //没用了
    public void addPromotionUser(Map<Integer,Long> userMap){
        for(int rank : userMap.keySet()){
            long userId = userMap.get(rank);
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
            if(!chefDuelMap.containsKey(userId)){
                ChefDuelUpUser chefDuel2User = new ChefDuelUpUser();
                chefDuel2User.setActivityId(activityInfo.getActivityId());
                chefDuel2User.setServerId(userBaseInfo.getServerId());
                chefDuel2User.setUserId(userId);
                chefDuel2User.setPos(rank);
                chefDuel2User.setType(2);
                chefDuelMap.put(chefDuel2User.getUserId(),chefDuel2User);
                synchronized (needInsertUserList){
                    needInsertUserList.add(chefDuel2User);
                }
            }
        }
    }

    //自己有什么钥匙，是不是能吃
    private boolean canJoinSpoon(long homeUserId,List<Integer> spoonIdList){
        ChefDuelUpUser cookData = chefDuelMap.get(homeUserId);
        List<Integer> forbidSpoonIdList = new ArrayList<>();
        if(cookData != null){
            forbidSpoonIdList = cookData.getForbiddenSpoonList();
            for(int spoonId : spoonIdList){
                if(!forbidSpoonIdList.contains(spoonId)){
                    return true;
                }
            }
        }
        return false;
    }
    private RandomHelper randomHelper = new RandomHelper();

    //获取一个随机的自己可以参加的玩家
    public void getRandomCanJoinUser(long serverId,long userId,long nowUserId,List<Integer> spoonIdList){
        ChefDuelProto.ChefDuel2CanJoinUserRespMsg.Builder respMsg = ChefDuelProto.ChefDuel2CanJoinUserRespMsg.newBuilder();
        respMsg.setRet(GameErrorCode.E_CHEF_DUEL2_GET_CAN_JOIN_USER_NO);
        List<Long> userIdList = new ArrayList<>(openChefDuelTableMap.keySet());
        userIdList.remove(nowUserId);
        while (userIdList.size() > 0){
            int randomIndex = randomHelper.next(0,userIdList.size());
            long homeUserId = userIdList.get(randomIndex);
            userIdList.remove(randomIndex);
            if(homeUserId != userId && homeUserId != nowUserId) {
                if(!canJoinSpoon(homeUserId,spoonIdList))continue;
                for (ChefDuel2DishTable chefDuel2DishTable : new ArrayList<>(openChefDuelTableMap.get(homeUserId).values())) {
                    Map<Long, ChefDuel2Joiner> userIdlList = chefDuel2DishTable.getChefDuel2JoinerMap();
                    if (!userIdlList.containsKey(userId)) {
                        respMsg.setRet(0);
                        ChefDuelProto.ChefDuel2CookerTempMsg.Builder userInfo = ChefDuelProto.ChefDuel2CookerTempMsg.newBuilder();
                        userInfo.setServerId(chefDuel2DishTable.getServerId());
                        userInfo.setUserId(chefDuel2DishTable.getUserId());
                        userInfo.setCanEat(true);
                        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(chefDuel2DishTable.getUserId());
                        if (userBaseInfo == null) {
                            continue;
                        }
                        userInfo.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                        userInfo.setActivityId(activityInfo.getActivityId());
                        respMsg.setUserInfo(userInfo);
                        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_GET_CAN_JOIN_USER, respMsg);
                        MessageHelper.sendPacket(serverId, userId, pbMsg);
                        return;
                    }
                }
            }
        }
        /*for(long homeUserId : new ArrayList<>(openChefDuelTableMap.keySet())){
            if(homeUserId != userId && homeUserId != nowUserId) {
                if(!canJoinSpoon(homeUserId,spoonIdList))continue;
                for (ChefDuel2DishTable chefDuel2DishTable : new ArrayList<>(openChefDuelTableMap.get(homeUserId).values())) {
                    Map<Long, ChefDuel2Joiner> userIdlList = chefDuel2DishTable.getChefDuel2JoinerMap();
                    if (!userIdlList.containsKey(userId)) {
                        respMsg.setRet(0);
                        ChefDuelProto.ChefDuel2CookerTempMsg.Builder userInfo = ChefDuelProto.ChefDuel2CookerTempMsg.newBuilder();
                        userInfo.setServerId(chefDuel2DishTable.getServerId());
                        userInfo.setUserId(chefDuel2DishTable.getUserId());
                        userInfo.setCanEat(true);
                        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(chefDuel2DishTable.getUserId());
                        if (userBaseInfo == null) {
                            continue;
                        }
                        userInfo.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                        respMsg.setUserInfo(userInfo);
                        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_GET_CAN_JOIN_USER, respMsg);
                        MessageHelper.sendChannelPacket(serverId, userId, pbMsg);
                        return;
                    }
                }
            }
        }*/
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_GET_CAN_JOIN_USER, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }


    //设置汤勺类型，别人不能用这个类型入座
    public void forbidSpoon(long serverId,long userId,List<Integer> forbidSpoonIdList){
        ChefDuelUpUser userData = chefDuelMap.get(userId);
        if(userData != null){
            userData.setForbiddenSpoonList(forbidSpoonIdList);
            synchronized (needUpdateUserList){
                if(!needUpdateUserList.contains(userData)){
                    needUpdateUserList.add(userData);
                }
            }
            ChefDuelProto.ChefDuel2ForbidSpoonRespMsg.Builder respMsg = ChefDuelProto.ChefDuel2ForbidSpoonRespMsg.newBuilder();
            respMsg.setRet(0);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CROSS_CHEF_DUEL2_FORBID_SPOON, respMsg);
            MessageHelper.sendPacket(serverId, userId, pbMsg);
        }
    }

    //按照排名给桌子排下序
    private void rankToPos(){
        List<ChefDuelUpUser> upUserList = new ArrayList<>(chefDuelMap.values());
        upUserList.sort(new CrossChefDuel3.PosSort());
        int rank = 1;
        for(ChefDuelUpUser chefDuelUpUser : upUserList){
            chefDuelUpUser.setRank(rank);
            chefDuelUpUser.setPos(rank);
            rank++;
        }
    }

    //从大到小
    static class PosSort implements Comparator<ChefDuelUpUser> {
        @Override
        public int compare(ChefDuelUpUser o1, ChefDuelUpUser o2) {
            if (o1.getLastScore() == o2.getLastScore()) {
                return 0;
            }
            if (o1.getLastScore() <= o2.getLastScore()) {
                return 1;
            }
            return -1;
        }
    }

    /**
     * 1进2
     */
    public void addPromotionUser(long serverId,List<ChefDuelProto.CrossChefDuelWindUpCookerTempMsg> userListMsg){
        boolean sortFlag = false;
        for(ChefDuelProto.CrossChefDuelWindUpCookerTempMsg tempMsg : userListMsg){
            long userId = tempMsg.getUserId();
            UserBaseInfo userBaseInfo = PlayerBasePb.parseToUserBaseInfo(tempMsg.getPlayerBaseData());
            CrossUserMgr.updateUserBaseInfo(userId,userBaseInfo);
            if(!chefDuelMap.containsKey(userId)){
                sortFlag = true;
                ChefDuelUpUser chefDuel2User = new ChefDuelUpUser();
                chefDuel2User.setActivityId(activityInfo.getActivityId());
                chefDuel2User.setServerId(serverId);
                chefDuel2User.setUserId(userId);
                chefDuel2User.setPreRank(tempMsg.getRank());
                chefDuel2User.setPos(chefDuelMap.size() + 1);
                chefDuel2User.setType(2);
                chefDuel2User.setLastScore(tempMsg.getScore());
                chefDuel2User.setForbiddenSpoonList(new ArrayList<>());
                chefDuelMap.put(chefDuel2User.getUserId(),chefDuel2User);
                synchronized (needInsertUserList){
                    needInsertUserList.add(chefDuel2User);
                }
            }
        }
        if(sortFlag){
            rankToPos();
        }
    }

    public void timerTask(){
        tableCheck();
        syncHorseNotice();

        syncCookerServer();
        syncActivityInfoToServer();

        syncSettingChangeToServer();
    }

    private void syncSettingChangeToServer() {
        try {
            if (spoonSettingChangeSet.isEmpty()) {
                return;
            }
            Set<Long> tempSet = null;
            synchronized (spoonSettingChangeSet){
                if(!spoonSettingChangeSet.isEmpty()){
                    tempSet = new HashSet<>(spoonSettingChangeSet);
                    spoonSettingChangeSet.clear();
                }
            }
            if(tempSet != null && !tempSet.isEmpty()){
                ChefDuelProto.ChefDuel2SettingSpoonChangeNotifyMsg.Builder clientMsg = ChefDuelProto.ChefDuel2SettingSpoonChangeNotifyMsg.newBuilder();
                for (long uid : tempSet) {
                    CrossChefDuel2AutoJoinSpoon autoJoinSpoon = autoJoinSpoonMap.get(uid);
                    if(autoJoinSpoon != null){
                        ChefDuelProto.ChefDuel2UserSettingSpoon.Builder builder = ChefDuelProto.ChefDuel2UserSettingSpoon.newBuilder();
                        builder.setUserId(uid);
                        for (Map.Entry<Integer, Integer> entry : autoJoinSpoon.getSpoonMap().entrySet()) {
                            builder.addSetting(ChefDuelProto.ChefDuel2SettingSpoon.newBuilder().setSpoonId(entry.getKey()).setSpoonNum(entry.getValue()));
                        }
                        clientMsg.addUserSet(builder);
                    }
                }
                for (long sid : activityInfo.getServerIdList2()) {
                    YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CHEF_DUEL2_SETTING_SPOON_CHANGE_FROM_CROSS, clientMsg);
                    MessageHelper.sendPacket(sid, 0, pbMsg);
                }
            }
        }catch (Exception e){
            logger.error("", e);
        }
    }

    private void syncActivityInfoToServer() {
        if(syncServerIdList.isEmpty()){
            return;
        }
        ChefDuelProto.CrossChefDuel2ActivityInfoSync.Builder builder = ChefDuelProto.CrossChefDuel2ActivityInfoSync.newBuilder();
        builder.setActivity(CrossActivityPb.parseActivityTempMsg(activityInfo));
        for (Long sid : new ArrayList<>(syncServerIdList)) {
            MessageHelper.sendPacket(sid, 0, YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_ACTIVITY_SYNC, builder));
        }
    }

    public void syncLoginData(){

    }

    public CrossChefDuel2(ActivityInfo acInfo){
        activityInfo = acInfo;
        this.syncServerIdList = new ConcurrentHashSet<>(getNeedSyncServerIdList());
//		reload();
    }

    public void initJonList(List<ChefDuel2UserJoinData> joinList){
        for(ChefDuel2UserJoinData chefDuel2UserJoinData : joinList){
            joinMap.put(chefDuel2UserJoinData.getUserId1(),chefDuel2UserJoinData);
        }
    }

    private void initOpenTable(){
        for(Map<Integer, ChefDuel2DishTable> chefDuel2DishTableMap : chefDuelTableMap.values()){
            for(ChefDuel2DishTable chefDuel2DishTable : chefDuel2DishTableMap.values()){
                if(chefDuel2DishTable.getOverTime() == 0){
                    if(!openChefDuelTableMap.containsKey(chefDuel2DishTable.getUserId())){
                        openChefDuelTableMap.put(chefDuel2DishTable.getUserId(),new ConcurrentHashMap<>());
                    }
                    openChefDuelTableMap.get(chefDuel2DishTable.getUserId()).put(chefDuel2DishTable.getNo(),chefDuel2DishTable);
                }
            }
        }
    }

    public boolean reload() {
        chefDuelTableMap = new CrossChefDuelDaoImpl().getCrossDishTableMap(activityInfo.getActivityId());
        chefDuelMap = new CrossChefDuelDaoImpl().getCrossChefDuel2UserMap(activityInfo.getActivityId());

        campUserRankMap.put(1, new CrossChefDuel2RankListModel());
        campUserRankMap.put(2, new CrossChefDuel2RankListModel());

        joinList = new CrossChefDuelDaoImpl().getChefDuel2UserJoinData(getActivityId());
        initJonList(joinList);

        autoJoinSpoonMap = new CrossCommonActivityDataDaoImpl<CrossChefDuel2AutoJoinSpoon>().
                getActivityDataLongMap(CrossChefDuel2AutoJoinSpoon.class, getActivityId(), "userId");

        List<ChefDuel2AutoJoinRecord> autoJoinRecords = new CrossCommonActivityDataDaoImpl<ChefDuel2AutoJoinRecord>().
                getActivityDataList(ChefDuel2AutoJoinRecord.class, getActivityId());

        for (ChefDuel2AutoJoinRecord autoJoinRecord : autoJoinRecords) {
            long userId = autoJoinRecord.getUserId();
            long hostId = autoJoinRecord.getHostId();
            if (!autoJoinRecordMap.containsKey(userId)) {
                autoJoinRecordMap.put(userId, new HashMap<>());
            }
            Map<Long, ChefDuel2AutoJoinRecord> recordMap = autoJoinRecordMap.get(userId);
            if (!recordMap.containsKey(hostId)) {
                recordMap.put(hostId, autoJoinRecord);
            }
        }


//        repair();
        initOpenTable();
        rankToPos();
        // 初始化自动回宴线程池，开1个线程池，线程数量2个
        if(null == autoJoinThreadPool) {
            autoJoinThreadPool = new ThreadTaskManger(1, "autoJoinThreadPool", 2);
        }
        return true;
    }

    public boolean save() {
        List<ChefDuel2DishTable> tempInsertList;
        synchronized (needInsertTableList) {
            tempInsertList = new ArrayList<>(needInsertTableList);
            needInsertTableList.clear();
        }
        if (tempInsertList.size() > 0) {
            new CrossChefDuelDaoImpl().addCrossDishTableList(tempInsertList);
        }
        List<ChefDuel2DishTable> tempUpdateList;
        synchronized (needUpdateTableList) {
            tempUpdateList = new ArrayList<>(needUpdateTableList);
            needUpdateTableList.clear();
        }
        if (tempUpdateList.size() > 0) {
            new CrossChefDuelDaoImpl().updateCrossDishTableList(tempUpdateList);
        }
        List<ChefDuelUpUser> tempChefDuel2UserInsertList;
        synchronized (needInsertUserList){
            tempChefDuel2UserInsertList = new ArrayList<>(needInsertUserList);
            needInsertUserList.clear();
        }
        if(tempChefDuel2UserInsertList.size() > 0){
            new CrossChefDuelDaoImpl().addCrossChefDuelUserList(tempChefDuel2UserInsertList);
        }
        List<ChefDuelUpUser> tempChefDuel2UserUpdateList;
        synchronized (needUpdateUserList){
            tempChefDuel2UserUpdateList = new ArrayList<>(needUpdateUserList);
            needUpdateUserList.clear();
        }
        if(tempChefDuel2UserUpdateList.size() > 0){
            new CrossChefDuelDaoImpl().updateCrossChefDuelUserList(tempChefDuel2UserUpdateList);
        }

        List<ChefDuel2UserJoinData> tempJoinInsertList;
        synchronized (joinInsertList) {
            tempJoinInsertList = new ArrayList<>(joinInsertList);
            joinInsertList.clear();
        }
        if (tempJoinInsertList.size() > 0) {
            new CrossChefDuelDaoImpl().addJoinRelationList(tempJoinInsertList);
        }

        List<ChefDuel2UserJoinData> tempJoinUpdateList;
        synchronized (joinUpdateList) {
            tempJoinUpdateList = new ArrayList<>(joinUpdateList);
            joinUpdateList.clear();
        }
        if (tempJoinUpdateList.size() > 0) {
            new CrossChefDuelDaoImpl().updateJoinRelationList(tempJoinUpdateList);
        }

        for (CrossChefDuel2AutoJoinSpoon spoon : autoJoinSpoonMap.values()) {
            if (spoon.isUpdateOption()) {
                new CrossCommonActivityDataDaoImpl<CrossChefDuel2AutoJoinSpoon>().update(spoon);
            } else if (spoon.isInsertOption()) {
                new CrossCommonActivityDataDaoImpl<CrossChefDuel2AutoJoinSpoon>().add(spoon);
            }
        }

        for (Map.Entry<Long, Map<Long, ChefDuel2AutoJoinRecord>> entry : autoJoinRecordMap.entrySet()) {
            for (Map.Entry<Long, ChefDuel2AutoJoinRecord> recordEntry : entry.getValue().entrySet()) {
                ChefDuel2AutoJoinRecord record = recordEntry.getValue();
                if (record.isUpdateOption()) {
                    new CrossCommonActivityDataDaoImpl<ChefDuel2AutoJoinRecord>().update(record);
                } else if (record.isInsertOption()) {
                    new CrossCommonActivityDataDaoImpl<ChefDuel2AutoJoinRecord>().add(record);
                }
            }
        }

        return true;
    }

    public boolean init() {
        return reload();
    }

    public boolean stop() {
        return false;
    }

    /**
     * 预留接口
     */
    public void repair() { 
    }

    public List<Long> getNeedSyncServerIdList(){
        if(activityInfo.getServerIdList2().isEmpty()){
            return Collections.emptyList();
        }
        List<Long> list = new ArrayList<>();
        for (Long id : activityInfo.getServerIdList2()) {
            if(activityInfo.getServerIdList().contains(id)){
                continue;
            }
            list.add(id);
        }
        return list;
    }

    public Map<Integer, Integer> getCampCountMap() {
        return campCountMap;
    }

    public CampRankListModel getCampRankListModel() {
        return campRankListModel;
    }

    public Map<Integer, CrossChefDuel2RankListModel> getCampUserRankMap() {
        return campUserRankMap;
    }

    public Map<Long, ChefDuelUpUser> getChefDuelMap() {
        return chefDuelMap;
    }


    //
    /**
     * 自动回访试吃
     *
     * @param serverId 回发游戏服ID
     * @param reqMsg  reqMsg
     */
    public void autoJoinTaste(long serverId, ChefDuelProto.CrossChefDuel2AutoJoinTasteMsg reqMsg) {
        ChefDuelProto.CrossChefDuel2AutoJoinInfoMsg autoJoinInfo = reqMsg.getAutoJoinInfo();
        long hostId = autoJoinInfo.getHostId();
        long guestId = autoJoinInfo.getGuestId();
        int hostActivityId = autoJoinInfo.getHostActivityId();
        int guestActivityId = autoJoinInfo.getGuestActivityId();
        int spoonId = autoJoinInfo.getSpoonId();
        int spoonCnt = reqMsg.getSpoonCnt();

        if (!chefDuelTableMap.containsKey(hostId)) {
            logger.error("摊主桌子信息未找到! 活动ID:{} 摊主ID:{}", hostActivityId, hostId);
            return;
        }

        ChefDuel2Spoon cookBoy2Spoon = CrossChefDuelActivityMgr.getChefDuel2Spoon(hostActivityId, spoonId);
        if (cookBoy2Spoon == null) {
            logger.error("汤勺配置未找到! 活动ID:{} 摊主ID:{} 汤勺ID {}", hostActivityId, hostId, spoonId);
            return;
        }

//        CrossUserMgr.updateUserBaseInfo(hostId, hostInfo); // todo 不同的跨服是否需要添加摊主的信息
        ChefDuel2UserInfo hostBaseInfo = new ChefDuel2UserInfo(hostActivityId, spoonId, hostId, autoJoinInfo.getHostServerId());
        ChefDuel2UserInfo guestBaseInfo = new ChefDuel2UserInfo(guestActivityId, spoonId, guestId, serverId);

        int realCost = 0; // 实际试吃的数量
        ChefDuelUpUser upUser = chefDuelMap.get(hostId);
        synchronized (getUserLocker(hostId)){
            if(upUser.getSpoonLimit() < CrossChefDuelActivityMgr.getChefDuel2SpoonLimit(activityInfo.getActivityId(), spoonId)){
                for (ChefDuel2DishTable cookBoy2DishTable : openChefDuelTableMap.get(hostId).values()) {
                    synchronized (cookBoy2DishTable) {
                        Map<Long, ChefDuel2Joiner> joinerMap = cookBoy2DishTable.getChefDuel2JoinerMap();
                        if (cookBoy2DishTable.getOverTime() != 0) { // 桌子试吃时间结束
                            continue;
                        }
                        ChefDuel2DishConfig cookBoy2DishConfig = CrossChefDuelActivityMgr.getDishCondfig(getActivityId(), cookBoy2DishTable.getDishId());
                        if (cookBoy2DishConfig == null) { // 桌子类型配置未找到
                            continue;
                        }
                        if (cookBoy2DishTable.getChefDuel2JoinerMap().size() >= cookBoy2DishConfig.getSeat()) { // 满座
                            continue;
                        }
                        if (!CrossChefDuelActivityMgr.isActivityMatchTime(activityInfo)) { // 不在活动匹配期间
                            continue;
                        }
                        if (joinerMap.containsKey(guestId)) { // 访客已在阵中
                            continue;
                        }

                        try {
                            taste(cookBoy2DishTable, cookBoy2Spoon, hostBaseInfo, guestBaseInfo);
                        } catch (Exception e) { // 有异常就跳过这一桌
                            logger.error("小当家二阶段自动回访试吃错误！摊主活动ID:{} 摊主ID:{} 访客活动ID:{} 访客ID:{} 菜桌Id:{} 汤勺ID:{}",
                                    hostActivityId, hostId, guestActivityId, guestId, cookBoy2DishTable.getDishId(), spoonId);
                            continue;
                        }
                        realCost++;
                        int chefDuel2SpoonLimit = CrossChefDuelActivityMgr.getChefDuel2SpoonLimit(activityInfo.getActivityId(), spoonId);
                        if(chefDuel2SpoonLimit < Integer.MAX_VALUE) {
                            upUser.setSpoonLimit(1 + upUser.getSpoonLimit());
                        }

                        if (realCost == spoonCnt) { // 吃够携带来的汤勺数就提前结束
                            break;
                        }
                    }
                }
            }
        }
        synchronized (needUpdateUserList){
            if(!needUpdateUserList.contains(upUser)){
                needUpdateUserList.add(upUser);
            }
        }

        tableCheck();

        int itemId = CrossChefDuelActivityMgr.getChefDuel2IntegralItemId(guestActivityId); // 收益道具Id
        // 收益回区服发邮件
        if (realCost > 0) {
            Property hostProperty =
                    new Property(itemId, cookBoy2Spoon.getUserIntegral());
            sendReward(spoonId, realCost, hostBaseInfo, hostProperty);

            Property guestProperty =
                    new Property(itemId, cookBoy2Spoon.getJoinerIntegral());
            sendReward(spoonId, realCost, guestBaseInfo, guestProperty);
        }

        ChefDuelProto.CrossChefDuel2SyncAutoJoinResultMsg.Builder req =
                ChefDuelProto.CrossChefDuel2SyncAutoJoinResultMsg.newBuilder();
        req.setAutoJoinInfo(autoJoinInfo);
        req.setRestCnt(spoonCnt - realCost); // 返还剩余汤勺数
        req.setRealCnt(realCost);

        YanQuMessage pbReq = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_SYNC_AUTO_JOIN_RESULT, req);
        MessageHelper.sendPacket(serverId, guestId, pbReq);
    }

    /**
     * 同步自动回访数据
     *
     * @param serverId 访客服务器ID
     * @param reqMsg   reqMsg
     */
    public void syncAutoJoinData(long serverId, ChefDuelProto.CrossChefDuel2SyncAutoJoinDataMsg reqMsg) {
        ChefDuelProto.CrossChefDuel2AutoJoinInfoMsg info = reqMsg.getAutoJoinInfo();
        int spoonId = info.getSpoonId();
        long hostId = info.getHostId();

        ChefDuel2UserInfo hostInfo = new ChefDuel2UserInfo(info.getHostActivityId(), spoonId, hostId, info.getHostServerId());
        ChefDuel2UserInfo guestInfo = new ChefDuel2UserInfo(info.getGuestActivityId(), spoonId, info.getGuestId(), serverId);
        int guestActivityId = info.getGuestActivityId();
        long guestId = info.getGuestId();

        synchronized (getUserLocker(guestId)) {
            // 同步汤勺数量
            List<Integer> spoonIds = CrossChefDuelActivityMgr.getChefDuel2SpoonIds(guestActivityId);
            syncSpoonMap(reqMsg.getSpoonList(), guestId, spoonIds, guestActivityId);
            // 修改自动回访记录
            int realCnt = reqMsg.getRealCnt();
            ChefDuel2AutoJoinRecord record = getChefDuel2AutoJoinRecord(guestInfo, hostInfo);
            record.getSpoonMap().merge(spoonId, realCnt, Integer::sum); // 回访记录
            record.setLastJoinTime(System.currentTimeMillis());
        }

        synchronized (spoonSettingChangeSet) {
            spoonSettingChangeSet.add(guestId);
        }
    }

    /**
     * 同步自动回访汤勺数量
     */
    public void syncAutoJoinSpoon(long serverId, ChefDuelProto.CrossChefDuel2SyncAutoJoinSpoonMsg reqMsg) {
        int activityId = reqMsg.getActivityId();
        long userId = reqMsg.getUserId();
        List<Integer> spoonIds = CrossChefDuelActivityMgr.getChefDuel2SpoonIds(activityId);
        synchronized (getUserLocker(userId)) {
            if (!autoJoinSpoonMap.containsKey(userId)) {
                CrossChefDuel2AutoJoinSpoon tmp = new CrossChefDuel2AutoJoinSpoon(activityId, userId, 0);
                ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
                for (Integer spoonId : spoonIds) {
                    map.put(spoonId, 0);
                }
                tmp.setServerId(serverId);
                tmp.setSpoonMap(map);
                autoJoinSpoonMap.put(userId, tmp);
            }

            List<ChefDuelProto.ChefDuel2SpoonTempMsg> spoonList = reqMsg.getSpoonList();
            syncSpoonMap(spoonList, userId, spoonIds, activityId);
        }
        synchronized (spoonSettingChangeSet) {
            spoonSettingChangeSet.add(userId);
        }
    }

    /**
     * 同步汤勺数量
     *
     * @param spoonList  汤勺列表
     * @param userId     访客ID
     * @param spoonIds   汤勺配置ID
     * @param activityId 访客活动ID
     */
    private void syncSpoonMap(List<ChefDuelProto.ChefDuel2SpoonTempMsg> spoonList, long userId, List<Integer> spoonIds, int activityId) {
        CrossChefDuel2AutoJoinSpoon autoJoinSpoon = autoJoinSpoonMap.get(userId);
        ConcurrentHashMap<Integer, Integer> tmpSpoonMap = new ConcurrentHashMap<>();
        for (ChefDuelProto.ChefDuel2SpoonTempMsg spoon : spoonList) {
            int id = spoon.getId();
            int cnt = spoon.getCnt();
            if (!spoonIds.contains(id)) {
                logger.error("自动回访汤勺数量同步失败，不正确的汤勺ID 活动ID:{} 访客ID:{} 汤勺ID:{} 配置汤勺列表:{}",
                        activityId, userId, id, spoonIds);
                continue;
            }
            tmpSpoonMap.put(id, cnt);
        }
        autoJoinSpoon.setSpoonMap(tmpSpoonMap);
    }

    /**
     * 获取访客对摊主的自动回访记录
     *
     * @param guestBaseInfo 访客
     * @param hostBaseInfo  摊主
     * @return ChefDuel2AutoJoinRecord
     */
    private ChefDuel2AutoJoinRecord getChefDuel2AutoJoinRecord(ChefDuel2UserInfo guestBaseInfo, ChefDuel2UserInfo hostBaseInfo) {

        if (!autoJoinRecordMap.containsKey(guestBaseInfo.getUserId())) {
            autoJoinRecordMap.put(guestBaseInfo.getUserId(), new ConcurrentHashMap<>());
        }
        ChefDuel2AutoJoinRecord joinRecord = autoJoinRecordMap.get(guestBaseInfo.getUserId()).get(hostBaseInfo.getUserId());
        if(joinRecord  == null){
            joinRecord = new ChefDuel2AutoJoinRecord();
            joinRecord.setActivityId(guestBaseInfo.getActivityId());
            joinRecord.setUserId(guestBaseInfo.getUserId());
            joinRecord.setServerId(guestBaseInfo.getServerId());
            joinRecord.setHostActivityId(hostBaseInfo.getActivityId());
            joinRecord.setHostId(hostBaseInfo.getUserId());
            joinRecord.setHostServerId(hostBaseInfo.getServerId());
            ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
            List<Integer> confSpoonIds = CrossChefDuelActivityMgr.getChefDuel2SpoonIds(guestBaseInfo.getActivityId());
            for (int confSpoonId : confSpoonIds) {
                map.put(confSpoonId, 0);
            }
            joinRecord.setSpoonMap(map);
            joinRecord.setInsertOption();
            autoJoinRecordMap.get(guestBaseInfo.getUserId()).put(hostBaseInfo.getUserId(), joinRecord);
        }
        return joinRecord;
    }

    /**
     * 自动回访试吃，基本是joinTable的原有逻辑
     *
     * @param cookBoy2DishTable 菜桌
     * @param cookBoy2Spoon     汤勺
     * @param host              摊主
     * @param guest             访客
     */
    private void taste(ChefDuel2DishTable cookBoy2DishTable, ChefDuel2Spoon cookBoy2Spoon,
                       ChefDuel2UserInfo host, ChefDuel2UserInfo guest) {
        ChefDuelUpUser cookData = chefDuelMap.get(host.getUserId());
        List<Integer> forbidSpoonIdList = new ArrayList<>();
        if (cookData != null) {
            forbidSpoonIdList = cookData.getForbiddenSpoonList();
        }

        ChefDuel2Joiner cookBoy2Joiner = new ChefDuel2Joiner();
        cookBoy2Joiner.setServerId(guest.getServerId());
        cookBoy2Joiner.setUserId(guest.getUserId());
        cookBoy2Joiner.setGifttId(host.getSpoonId());
        Map<Long, ChefDuel2Joiner> joinerMap = cookBoy2DishTable.getChefDuel2JoinerMap();
        cookBoy2Joiner.setPos(joinerMap.size() + 1);
        joinerMap.put(cookBoy2Joiner.getUserId(), cookBoy2Joiner); // 上座
        cookBoy2DishTable.setChefDuel2JoinerMap(joinerMap);
        cookBoy2DishTable.setIntegral(cookBoy2DishTable.getIntegral() + cookBoy2Spoon.getUserIntegral());

        ChefDuelProto.CrossChefDuel2JoinTableMsg.Builder joinMsg = ChefDuelProto.CrossChefDuel2JoinTableMsg.newBuilder();
        joinMsg.setRet(0);
        joinMsg.setActivityId(getActivityId());
        joinMsg.setJoinerUserId(guest.getUserId());
        joinMsg.setHomeUserId(host.getUserId());
        joinMsg.setTableId(cookBoy2DishTable.getDishId());
        joinMsg.setSpoonId(host.getSpoonId());
        joinMsg.addAllForbidSpoonId(forbidSpoonIdList);
        if (guest.getActivityId() > 0) {
            joinMsg.setActivityId(guest.getActivityId());
            joinMsg.setOtherActivityId(host.getActivityId());
        }
        joinMsg.setAutoJoin(1);
        YanQuMessage pbJoinerMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_JOIN_JOINER, joinMsg);

        ChefDuelProto.CrossChefDuel2JoinTableMsg.Builder msg = ChefDuelProto.CrossChefDuel2JoinTableMsg.newBuilder();
        msg.setRet(0);
        msg.setActivityId(getActivityId());
        msg.setJoinerUserId(guest.getUserId());
        msg.setHomeUserId(host.getUserId());
        msg.setTableId(cookBoy2DishTable.getDishId());
        msg.setSpoonId(host.getSpoonId());
        msg.addAllForbidSpoonId(forbidSpoonIdList);
        msg.setAutoJoin(1);
        YanQuMessage pbOpenerMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_JOIN_OPENER, msg);
        MessageHelper.sendPacket(guest.getServerId(), guest.getUserId(), pbJoinerMsg);
        MessageHelper.sendPacket(cookBoy2DishTable.getServerId(), host.getUserId(), pbOpenerMsg);

        newJoin(host.getUserId(), guest.getUserId(), guest.getActivityId()); // 添加回宴次数
        syncTableServer(cookBoy2DishTable, cookBoy2Spoon.getUserIntegral());

        synchronized (needUpdateTableList) {
            if (!needUpdateTableList.contains(cookBoy2DishTable)) {
                needUpdateTableList.add(cookBoy2DishTable);
            }
        }
        synchronized (needSyncUserList) {
            if (!needSyncUserList.contains(chefDuelMap.get(host.getUserId()))) {
                needSyncUserList.add(chefDuelMap.get(host.getUserId()));
            }
        }

        addAutoJoinLog(cookBoy2DishTable.getNo(), host, guest);
    }

    /**
     * 添加加自动回访记录
     *
     * @param tableId 菜桌ID
     * @param host    摊主
     * @param guest   访客
     */
    private void addAutoJoinLog(int tableId, ChefDuel2UserInfo host, ChefDuel2UserInfo guest) {
        ChefDuel2AutoJoinLog log = new ChefDuel2AutoJoinLog();
        log.setActivityId(guest.getActivityId());
        log.setUserId(guest.getUserId());
        log.setServerId(guest.getServerId());
        log.setHostActivityId(host.getActivityId());
        log.setHostId(host.getUserId());
        log.setHostServerId(host.getServerId());
        log.setSpoonId(host.getSpoonId());
        log.setTableId(tableId);
        log.setJoinTime(System.currentTimeMillis());
        CrossAutoLogMgr.add(log);
    }

    /**
     * 发送给区服，去区服发送回访收益邮件
     *
     * @param spoonId  汤勺ID
     * @param count    回访次数
     * @param userInfo 用户信息
     * @param property 单项收益
     */
    private static void sendReward(int spoonId, int count, ChefDuel2UserInfo userInfo, Property property) {
        ChefDuelProto.CrossChefDuel2DealAutoJoinRewardMsg.Builder req =
                ChefDuelProto.CrossChefDuel2DealAutoJoinRewardMsg.newBuilder();
        req.setActivityId(userInfo.getActivityId());
        req.setUserId(userInfo.getUserId());
        req.setReward(property.toHelperString());
        req.setSpoonId(spoonId);
        req.setCount(count);

        YanQuMessage pbReq = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_DEAL_AUTO_JOIN_REWARD, req);
        MessageHelper.sendPacket(userInfo.getServerId(), userInfo.getUserId(), pbReq);
    }

    /**
     * 获取自动回访记录
     *
     * @param serverId 服务器ID
     * @param userId   用户ID
     */
    public void getAutoJoinRecord(long serverId, long userId) {
        ChefDuelProto.ChefDuel2GetAutoJoinRecordRespMsg.Builder respMsg = ChefDuelProto.ChefDuel2GetAutoJoinRecordRespMsg.newBuilder();
        respMsg.setRet(0);

        Map<Long, ChefDuel2AutoJoinRecord> recordMap = autoJoinRecordMap.get(userId);
        if(recordMap != null){
            for (Map.Entry<Long, ChefDuel2AutoJoinRecord> recordEntry : recordMap.entrySet()) {
                ChefDuel2AutoJoinRecord record = recordEntry.getValue();
                ChefDuelProto.ChefDuel2AutoJoinRecordTemp.Builder recordTemp =
                        ChefDuelProto.ChefDuel2AutoJoinRecordTemp.newBuilder();
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(record.getHostId()); // 摊主信息
                if (userBaseInfo != null) {
                    recordTemp.setUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                }
                for (Map.Entry<Integer, Integer> kv : record.getSpoonMap().entrySet()) {
                    ChefDuelProto.ChefDuel2SpoonTempMsg.Builder spoon = ChefDuelProto.ChefDuel2SpoonTempMsg.newBuilder();
                    spoon.setId(kv.getKey());
                    spoon.setCnt(kv.getValue());
                    recordTemp.addSpoon(spoon);
                }
                respMsg.addRecord(recordTemp);
            }
        }

        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CHEF_DUEL2_GET_AUTO_JOIN_RECORD, respMsg);
        MessageHelper.sendPacket(serverId, userId, pbMsg);
    }

    /**
     * 获取摊主可试吃数量
     *
     * @param serverId 回发游戏服ID
     * @param reqMsg   reqMsg
     */
    public void getTasteTableCnt(long serverId, ChefDuelProto.CrossChefDuel2GetTasteTableCntMsg reqMsg) {
        ChefDuelProto.CrossChefDuel2AutoJoinInfoMsg autoJoinInfo = reqMsg.getAutoJoinInfo();
        long hostId = autoJoinInfo.getHostId();
        long guestId = autoJoinInfo.getGuestId();
        int spoonId = autoJoinInfo.getSpoonId();

        ChefDuelProto.CrossChefDuel2SyncTasteTableCntMsg.Builder req = ChefDuelProto.CrossChefDuel2SyncTasteTableCntMsg.newBuilder();
        req.setRet(0);
        List<Integer> hostForbiddenSpoonIdList = getUserForbiddenSpoonIdList(hostId);
        if (hostForbiddenSpoonIdList.contains(spoonId)) {
            logger.info("摊主设置禁止该类型的汤勺自动回访，无法自动回访。 访客活动ID:{} 访客ID:{} 摊主活动ID:{} 摊主ID:{} 汤勺ID:{}",
                    autoJoinInfo.getGuestActivityId(), guestId, autoJoinInfo.getHostActivityId(), hostId, spoonId);
            return;
        }
        ChefDuelUpUser upUser = getChefDuelMap().get(hostId);
        synchronized (getUserLocker(hostId)){
            if(upUser.getSpoonLimit() >= CrossChefDuelActivityMgr.getChefDuel2SpoonLimit(activityInfo.getActivityId(), spoonId)){
                logger.info("摊主被赴宴道具使用次数达到上限，无法自动回访。 访客活动ID:{} 访客ID:{} 摊主活动ID:{} 摊主ID:{} 汤勺ID:{}",
                        autoJoinInfo.getGuestActivityId(), guestId, autoJoinInfo.getHostActivityId(), hostId, spoonId);
                return;
            }
        }

        req.setAutoJoinInfo(autoJoinInfo);
//        req.setCnt(getUserEatNum(hostId, guestId));
        req.setCnt(getUserEatNum(hostId, guestId) <= 0 ? 0 : 1);
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_SYNC_TASTE_TABLE_CNT, req);
        MessageHelper.sendPacket(serverId, guestId, pbMsg);
    }

    /**
     * 活动过期将设置的自动回访汤勺返回
     *
     * @param activityId 活动ID
     */
    public void sendAutoJoinSpoonRest(int activityId) {
        for (CrossChefDuel2AutoJoinSpoon spoon : autoJoinSpoonMap.values()) {
            if (spoon.getActivityId() != activityId) {
                continue;
            }
            if (spoon.getIsReturn() == 1) {
                continue;
            }

            ChefDuelProto.CrossChefDuel2DealAutoJoinSpoonRestMsg.Builder respMsg =
                    ChefDuelProto.CrossChefDuel2DealAutoJoinSpoonRestMsg.newBuilder();

            respMsg.setActivityId(spoon.getActivityId());
            respMsg.setUserId(spoon.getUserId());

            Map<Integer, Integer> spoonCntMap = new HashMap<>();
            List<Integer> confSpoonIds = CrossChefDuelActivityMgr.getChefDuel2SpoonIds(activityId);
            for (int confSpoonId : confSpoonIds) { // 返回必须有内容
                spoonCntMap.put(confSpoonId, 0);
            }

            Map<Long, ChefDuel2AutoJoinRecord> recordMap = autoJoinRecordMap.get(spoon.getUserId());
            if(recordMap != null){
                for (Map.Entry<Long, ChefDuel2AutoJoinRecord> recordEntry : recordMap.entrySet()) {
                    ChefDuel2AutoJoinRecord record = recordEntry.getValue();
                    if (record.getSpoonMap() != null) {
                        for (Map.Entry<Integer, Integer> kv : record.getSpoonMap().entrySet()) {
                            spoonCntMap.merge(kv.getKey(), kv.getValue(), Integer::sum);
                        }
                    }
                }
            }

            for (Map.Entry<Integer, Integer> kv : spoonCntMap.entrySet()) {
                ChefDuelProto.ChefDuel2SpoonTempMsg.Builder spoonTemp =
                        ChefDuelProto.ChefDuel2SpoonTempMsg.newBuilder();
                spoonTemp.setId(kv.getKey());
                spoonTemp.setCnt(kv.getValue());
                respMsg.addRecord(spoonTemp);
            }
            spoon.setIsReturn(1); // 这里先将返还标识置1，后续就不需要再同步过来了，实际汤勺数据以游戏服为准

            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_CHEF_DUEL2_DEAL_AUTO_JOIN_SPOON_REST,
                    respMsg);
            MessageHelper.sendPacket(spoon.getServerId(), spoon.getUserId(), pbMsg);
        }
    }

    public Map<Long, CrossChefDuel2AutoJoinSpoon> getAutoJoinSpoonMap() {
        return autoJoinSpoonMap;
    }
}
